NexusPi Git Node
RNode_Firmware.ino copilot/add-rtnode-configuration-options (9529fa8a) Text, 92.65 KB
T8b949e// Copyright (C) 2024, Mark Qvist
T8b949e// This program is free software: you can redistribute it and/or modify
T8b949e// it under the terms of the GNU General Public License as published by
T8b949e// the Free Software Foundation, either version 3 of the License, or
T8b949e// (at your option) any later version.
T8b949e// This program is distributed in the hope that it will be useful,
T8b949e// but WITHOUT ANY WARRANTY; without even the implied warranty of
T8b949e// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
T8b949e// GNU General Public License for more details.
T8b949e// You should have received a copy of the GNU General Public License
T8b949e// along with this program. If not, see <https://www.gnu.org/licenses/>.
T8b949e// CBA Reticulum includes must come before local to avoid collision with local defines
Tff7b72#Tff7b72ifdef HAS_RNS
Tff7b72#Tff7b72include T8b949e<Transport.h>
Tff7b72#Tff7b72include T8b949e<Reticulum.h>
Tff7b72#Tff7b72include T8b949e<Interface.h>
Tff7b72#Tff7b72include T8b949e<Log.h>
Tff7b72#Tff7b72include T8b949e<Bytes.h>
Tff7b72#Tff7b72include T8b949e<queue>
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72include T8b949e<Arduino.h>
Tff7b72#Tff7b72include T8b949e<SPI.h>
Tff7b72#Tff7b72include T8b949e"Utilities.h"
T8b949e// CBA Boundary Mode
T8b949e// NOTE: Boundary Mode is the legacy name. This firmware branch intends to
T8b949e// converge on a single Transport Mode, with the BOUNDARY_MODE symbol kept
T8b949e// temporarily as a compatibility shim during cleanup.
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
Tff7b72#Tff7b72include T8b949e"BoundaryMode.h"
Tff7b72#Tff7b72include T8b949e"TcpInterface.h"
Tff7b72#Tff7b72include T8b949e"BoundaryConfig.h"
Tff7b72#Tff7b72include T8b949e"Advertise.h"
Tff7b72#Tff7b72include T8b949e"esp_bt.h"
Tff7b72#Tff7b72endif
T8b949e// CBA FileSystem
Tff7b72#Tff7b72if defined(RNS_USE_FS)
Tff7b72#Tff7b72include T8b949e"FileSystem.h"
Tff7b72#Tff7b72else
Tff7b72#Tff7b72include T8b949e"NoopFileSystem.h"
Tff7b72#Tff7b72endif
T8b949e// CBA SD
Tff7b72#Tff7b72if HAS_SDCARD
Tff7b72#Tff7b72include T8b949e<SD.h>
Te6edf3SPIClass Td2a8ffSDSPITb4b4b4(Te6edf3HSPITb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Tff7b72#Tff7b72include T8b949e<esp_task_wdt.h>
Tff7b72#Tff7b72endif
T8b949e// WDT timeout
Tff7b72#Tff7b72define WDT_TIMEOUT 60 T8b949e// seconds
Te6edf3FIFOBuffer Te6edf3serialFIFOTb4b4b4;
Tff7b72uint8_t Te6edf3serialBufferTb4b4b4[Te6edf3CONFIG_UART_BUFFER_SIZETff7b72+T79c0ff1Tb4b4b4]Tb4b4b4;
Te6edf3FIFOBuffer16 Te6edf3packet_startsTb4b4b4;
Tff7b72uint16_t Te6edf3packet_starts_bufTb4b4b4[Te6edf3CONFIG_QUEUE_MAX_LENGTHTff7b72+T79c0ff1Tb4b4b4]Tb4b4b4;
Te6edf3FIFOBuffer16 Te6edf3packet_lengthsTb4b4b4;
Tff7b72uint16_t Te6edf3packet_lengths_bufTb4b4b4[Te6edf3CONFIG_QUEUE_MAX_LENGTHTff7b72+T79c0ff1Tb4b4b4]Tb4b4b4;
Tff7b72uint8_t Te6edf3packet_queueTb4b4b4[Te6edf3CONFIG_QUEUE_SIZETb4b4b4]Tb4b4b4;
Tff7b72volatile Tff7b72uint8_t Te6edf3queue_height Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72uint16_t Te6edf3queued_bytes Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72uint16_t Te6edf3queue_cursor Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72uint16_t Te6edf3current_packet_start Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72volatile Tff7b72bool Te6edf3serial_buffering Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72bool Te6edf3bt_init_ran Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_CONSOLE
Tff7b72#Tff7b72include T8b949e"Console.h"
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32 || PLATFORM == PLATFORM_NRF52
Tff7b72#Tff7b72define MODEM_QUEUE_SIZE 8
Tff7b72typedef Tff7b72struct Tb4b4b4{
Tffa657size_t Te6edf3lenTb4b4b4;
Tff7b72int Te6edf3rssiTb4b4b4;
Tff7b72int Te6edf3snr_rawTb4b4b4;
Tff7b72uint8_t Te6edf3dataTb4b4b4[Tb4b4b4]Tb4b4b4;
Tb4b4b4} Te6edf3modem_packet_tTb4b4b4;
Tff7b72static Te6edf3xQueueHandle Te6edf3modem_packet_queue Tff7b72= Tffa657NULLTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72char Te6edf3sbufTb4b4b4[T79c0ff128Tb4b4b4]Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72bool Te6edf3packet_ready Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72void Td2a8ffupdate_csma_parametersTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifdef HAS_RNS
T8b949e// CBA LoRa interface
Tff7b72class T56d364LoRaInterface Tff7b72: Tff7b72public Te6edf3RNSTff7b72:Tff7b72:Te6edf3InterfaceImpl Tb4b4b4{
Tff7b72publicTff7b72:
Te6edf3LoRaInterfaceTb4b4b4(Tb4b4b4) Tff7b72: Te6edf3RNSTff7b72:Tff7b72:Te6edf3InterfaceImplTb4b4b4(Ta5d6ff"Ta5d6ffLoRaInterfaceTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3_IN Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3_OUT Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3_HW_MTU Tff7b72= T79c0ff508Tb4b4b4;
Tb4b4b4}
Te6edf3LoRaInterfaceTb4b4b4(Tff7b72const Tff7b72char Tff7b72*Te6edf3nameTb4b4b4) Tff7b72: Te6edf3RNSTff7b72:Tff7b72:Te6edf3InterfaceImplTb4b4b4(Te6edf3nameTb4b4b4) Tb4b4b4{
Te6edf3_IN Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3_OUT Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3_HW_MTU Tff7b72= T79c0ff508Tb4b4b4;
Tb4b4b4}
Tff7b72virtual Tff7b72~Te6edf3LoRaInterfaceTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_name Tff7b72= Ta5d6ff"Ta5d6ffdeletedTa5d6ff"Tb4b4b4;
Tb4b4b4}
Tff7b72protectedTff7b72:
Tff7b72virtual Tff7b72void Te6edf3handle_incomingTb4b4b4(Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3dataTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffLoRaInterface.handle_incoming: (%u bytes) data: %sTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4.Td2a8ffsizeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dataTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLoRaInterface.handle_incoming: sending packet to rns...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3InterfaceImplTff7b72:Tff7b72:Te6edf3handle_incomingTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72virtual Tff7b72void Te6edf3send_outgoingTb4b4b4(Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3dataTb4b4b4) Tb4b4b4{
T8b949e// CBA NOTE header will be addded later by transmit function
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffLoRaInterface.send_outgoing: (%u bytes) data: %sTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4.Td2a8ffsizeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dataTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLoRaInterface.send_outgoing: adding packet to outgoing queue...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657size_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3dataTb4b4b4.Td2a8ffsizeTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3queue_height Tff7b72< Te6edf3CONFIG_QUEUE_MAX_LENGTH Tff7b72&Tff7b72& Te6edf3queued_bytes Tff7b72< Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Tb4b4b4{
Te6edf3queued_bytesTff7b72+Tff7b72+Tb4b4b4;
Te6edf3packet_queueTb4b4b4[Te6edf3queue_cursorTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3dataTb4b4b4.Te6edf3dataTb4b4b4(Tb4b4b4)Tb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3queue_cursor Tff7b72=Tff7b72= Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Te6edf3queue_cursor Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo16_isfullTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4) Tff7b72&Tff7b72& Te6edf3queued_bytes Tff7b72< Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3s Tff7b72= Te6edf3current_packet_startTb4b4b4;
Tff7b72int16_t Te6edf3e Tff7b72= Te6edf3queue_cursorT79c0ff-1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3e Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Te6edf3e Tff7b72= Te6edf3CONFIG_QUEUE_SIZET79c0ff-1Tb4b4b4;
Tff7b72uint16_t Te6edf3lTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3s Tff7b72!Tff7b72= Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3l Tff7b72= Tb4b4b4(Te6edf3s Tff7b72< Te6edf3eTb4b4b4) Tff7b72? Te6edf3e Tff7b72- Te6edf3s Tff7b72+ T79c0ff1 Tff7b72: Te6edf3CONFIG_QUEUE_SIZE Tff7b72- Te6edf3s Tff7b72+ Te6edf3e Tff7b72+ T79c0ff1Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3l Tff7b72= T79c0ff1Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3l Tff7b72>Tff7b72= Te6edf3MIN_LTb4b4b4) Tb4b4b4{
Te6edf3queue_heightTff7b72+Tff7b72+Tb4b4b4;
Te6edf3fifo16_pushTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4, Te6edf3sTb4b4b4)Tb4b4b4;
Te6edf3fifo16_pushTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4, Te6edf3lTb4b4b4)Tb4b4b4;
Te6edf3current_packet_start Tff7b72= Te6edf3queue_cursorTb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Perform post-send housekeeping
Te6edf3InterfaceImplTff7b72:Tff7b72:Te6edf3handle_outgoingTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4;
T8b949e// CBA logger callback
Tff7b72void Td2a8ffon_logTb4b4b4(Tff7b72const Tff7b72charTff7b72* Te6edf3msgTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LogLevel Te6edf3levelTb4b4b4) Tb4b4b4{
T8b949e/*
Serial.print(RNS::getTimeString());
Serial.print(" [");
Serial.print(RNS::getLevelName(level));
Serial.print("] ");
Serial.println(msg);
Serial.flush();
*/
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff [Ta5d6ff"Tb4b4b4) Tff7b72+ Te6edf3RNSTff7b72:Tff7b72:Te6edf3getLevelNameTb4b4b4(Te6edf3levelTb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ff] Ta5d6ff" Tff7b72+ Te6edf3msg Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Td2a8fflineTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef HAS_SDCARD
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/logfile.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_SDCARD
Tb4b4b4}
T8b949e// CBA receive packet callback
Tff7b72void Td2a8ffon_receive_packetTb4b4b4(Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3rawTb4b4b4, Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3InterfaceTff7b72& Te6edf3interfaceTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef HAS_SDCARD
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLogging receive packet to SDTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff recv: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3rawTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/tracefile.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Packet Te6edf3packetTb4b4b4(Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4, Te6edf3rawTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3unpackTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff recv: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3dumpStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/tracedetails.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_SDCARD
Tb4b4b4}
T8b949e// CBA transmit packet callback
Tff7b72void Td2a8ffon_transmit_packetTb4b4b4(Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3rawTb4b4b4, Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3InterfaceTff7b72& Te6edf3interfaceTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef HAS_SDCARD
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffLogging transmit packet to SDTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff send: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3rawTb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/tracefile.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Packet Te6edf3packetTb4b4b4(Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4, Te6edf3rawTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3unpackTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72String Td2a8ffline Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3getTimeStringTb4b4b4(Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Ta5d6ff"Ta5d6ff send: Ta5d6ff"Tb4b4b4) Tff7b72+ Tff7b72StringTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3dumpStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/tracedetails.txtTa5d6ff"Tb4b4b4, Te6edf3FILE_APPENDTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Te6edf3fileTb4b4b4.Td2a8ffwriteTb4b4b4(Tb4b4b4(Tff7b72uint8_tTff7b72*Tb4b4b4)Td2a8fflineTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Td2a8fflineTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Td2a8ffcloseTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_SDCARD
Tb4b4b4}
T8b949e// CBA RNS
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Reticulum Td2a8ffreticulumTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Interface Td2a8fflora_interfaceTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Td2a8ffFileSystem Td2a8fffilesystemTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Boundary mode: TCP backbone interface + state
Te6edf3BoundaryState Te6edf3boundary_state Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Interface Td2a8fftcp_rns_interfaceTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Te6edf3TcpInterfaceTff7b72* Te6edf3tcp_interface_ptr Tff7b72= Tffa657nullptrTb4b4b4;
T8b949e// Local TCP server (MODE_ACCESS_POINT, doesn't forward announces)
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Interface Td2a8fflocal_tcp_rns_interfaceTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4)Tb4b4b4;
Te6edf3TcpInterfaceTff7b72* Te6edf3local_tcp_interface_ptr Tff7b72= Tffa657nullptrTb4b4b4;
T8b949e// RTC memory flag — survives software reset but not power cycle
Te6edf3RTC_NOINIT_ATTR Tff7b72uint32_t Te6edf3boundary_config_requestTb4b4b4;
Tff7b72#Tff7b72define BOUNDARY_CONFIG_MAGIC 0xC0F19A7E
T8b949e// RTC flag to skip config portal on next boot (set when user powers off from WCC)
Te6edf3RTC_NOINIT_ATTR Tff7b72uint32_t Te6edf3boundary_skip_configTb4b4b4;
Tff7b72#Tff7b72define BOUNDARY_SKIP_MAGIC 0x5E1FC0F0
T8b949e// Bootloop detection: count rapid reboots in RTC memory.
T8b949e// After BOOTLOOP_THRESHOLD consecutive reboots within BOOTLOOP_WINDOW_MS,
T8b949e// force entry into the config portal so the user can fix settings.
Tff7b72#Tff7b72define BOOTLOOP_THRESHOLD 5
Tff7b72#Tff7b72define BOOTLOOP_WINDOW_MS 120000 T8b949e// 2 minutes
Tff7b72#Tff7b72define BOOTLOOP_MAGIC 0xB007100D
Te6edf3RTC_NOINIT_ATTR Tff7b72uint32_t Te6edf3bootloop_magicTb4b4b4;
Te6edf3RTC_NOINIT_ATTR Tff7b72uint32_t Te6edf3bootloop_countTb4b4b4;
Te6edf3RTC_NOINIT_ATTR Tff7b72uint32_t Te6edf3bootloop_first_boot_msTb4b4b4;
T8b949e// Node public hash — cached in RTC so the config portal can display it without
T8b949e// needing to start RNS. Populated after the transport destination is created
T8b949e// on a normal boot; survives software reboots into the captive portal.
Tff7b72#Tff7b72define NODE_HASH_RTC_MAGIC 0x504B4841UL T8b949e// "PKHA"
Te6edf3RTC_NOINIT_ATTR Tff7b72uint32_t Te6edf3rtc_node_hash_magicTb4b4b4;
Te6edf3RTC_NOINIT_ATTR Tff7b72char Te6edf3rtc_node_hash_hexTb4b4b4[T79c0ff33Tb4b4b4]Tb4b4b4; T8b949e// 32 hex chars + NUL
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif T8b949e// HAS_RNS
Tff7b72void Tffa657setupTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Initialise serial communication
Te6edf3memsetTb4b4b4(Te6edf3serialBufferTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3serialBufferTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fifo_initTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3serialBufferTb4b4b4, Te6edf3CONFIG_UART_BUFFER_SIZETb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3serial_baudrateTb4b4b4)Tb4b4b4;
T8b949e// CBA Safely wait for serial initialization
Tff7b72while Tb4b4b4(Tff7b72!Td2a8ffSerialTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72> T79c0ff2000Tb4b4b4) Tb4b4b4{
Tff7b72breakTb4b4b4;
Tb4b4b4}
Td2a8ffdelayTb4b4b4(T79c0ff10Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// CBA Test
Td2a8ffdelayTb4b4b4(T79c0ff2000Tb4b4b4)Tb4b4b4;
T8b949e// Configure WDT
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_initTb4b4b4(Te6edf3WDT_TIMEOUTTb4b4b4, Tff7b72trueTb4b4b4)Tb4b4b4; T8b949e// enable panic so ESP32 restarts
Te6edf3esp_task_wdt_addTb4b4b4(Tffa657NULLTb4b4b4)Tb4b4b4; T8b949e// add current thread to WDT watch
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3CONFIG Tff7b72= T79c0ff0x01Tb4b4b4; T8b949e// Configure WDT to run when CPU is asleep
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3CRV Tff7b72= Te6edf3WDT_TIMEOUT Tff7b72* T79c0ff32768 Tff7b72+ T79c0ff1Tb4b4b4; T8b949e// set timeout
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3RREN Tff7b72= T79c0ff0x01Tb4b4b4; T8b949e// Enable the RR[0] reload register
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3TASKS_START Tff7b72= T79c0ff1Tb4b4b4; T8b949e// Start WDT
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3boot_seqTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffEEPROMTb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3EEPROM_SIZETb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Te6edf3setRxBufferSizeTb4b4b4(Te6edf3CONFIG_UART_BUFFER_SIZETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TDECK
Td2a8ffpinModeTb4b4b4(Te6edf3pin_poweronTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3pin_poweronTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3SD_CSTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3DISPLAY_CSTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3SD_CSTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3DISPLAY_CSTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3DISPLAY_BL_PINTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TECHO
Td2a8ffdelayTb4b4b4(T79c0ff200Tb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3pin_btn_usr1Tb4b4b4, Tff7b72INPUT_PULLUPTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3pin_btn_touchTb4b4b4, Tff7b72INPUT_PULLUPTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_LED_REDTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_LED_GREENTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_LED_BLUETb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff200Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3eeprom_beginTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffEEPROM initialisation failed.Tffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
T8b949e// Seed the PRNG for CSMA R-value selection
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
T8b949e// On ESP32, get the seed value from the
T8b949e// hardware RNG
Tff7b72unsigned Tff7b72long Te6edf3seed_val Tff7b72= Tb4b4b4(Tff7b72unsigned Tff7b72longTb4b4b4)Te6edf3esp_randomTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
T8b949e// On nRF, get the seed value from the
T8b949e// hardware RNG
Tff7b72unsigned Tff7b72long Te6edf3seed_val Tff7b72= Te6edf3get_rng_seedTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
T8b949e// Otherwise, get a pseudo-random seed
T8b949e// value from an unconnected analog pin
T8b949e//
T8b949e// CAUTION! If you are implementing the
T8b949e// firmware on a platform that does not
T8b949e// have a hardware RNG, you MUST take
T8b949e// care to get a seed value with enough
T8b949e// entropy at each device reset!
Tff7b72unsigned Tff7b72long Te6edf3seed_val Tff7b72= Td2a8ffanalogReadTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Td2a8ffrandomSeedTb4b4b4(Te6edf3seed_valTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_NP
Te6edf3led_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52 && HAS_NP == true
Te6edf3boot_seqTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1 && BOARD_MODEL != BOARD_HELTEC32_V4 && BOARD_MODEL != BOARD_HELTEC32_V3
T8b949e// Some boards need to wait until the hardware UART is set up before booting
T8b949e// the full firmware. In the case of the RAK4631, Heltec T114, and Heltec V3,
T8b949e// the line below will wait until a serial connection is actually established
T8b949e// with a master. Thus, it is disabled on these platforms.
Tff7b72while Tb4b4b4(Tff7b72!Td2a8ffSerialTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3serial_interrupt_initTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Configure input and output pins
Tff7b72#Tff7b72if HAS_INPUT
Te6edf3input_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_NP == false
Td2a8ffpinModeTb4b4b4(Te6edf3pin_led_rxTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffpinModeTb4b4b4(Te6edf3pin_led_txTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_TCXO == true
Tff7b72if Tb4b4b4(Te6edf3pin_tcxo_enable Tff7b72!Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{
Td2a8ffpinModeTb4b4b4(Te6edf3pin_tcxo_enableTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3pin_tcxo_enableTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
T8b949e// Initialise buffers
Te6edf3memsetTb4b4b4(Te6edf3pbufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3pbufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3cmdbufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3cmdbufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3packet_queueTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3packet_queueTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3packet_starts_bufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3packet_starts_bufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fifo16_initTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4, Te6edf3packet_starts_bufTb4b4b4, Te6edf3CONFIG_QUEUE_MAX_LENGTHTb4b4b4)Tb4b4b4;
Te6edf3memsetTb4b4b4(Te6edf3packet_lengths_bufTb4b4b4, T79c0ff0Tb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3packet_starts_bufTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3fifo16_initTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4, Te6edf3packet_lengths_bufTb4b4b4, Te6edf3CONFIG_QUEUE_MAX_LENGTHTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32 || PLATFORM == PLATFORM_NRF52
Te6edf3modem_packet_queue Tff7b72= Te6edf3xQueueCreateTb4b4b4(Te6edf3MODEM_QUEUE_SIZETb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3modem_packet_tTff7b72*Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// Set chip select, reset and interrupt
T8b949e// pins for the LoRa module
Tff7b72#Tff7b72if MODEM == SX1276 || MODEM == SX1278
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setPinsTb4b4b4(Te6edf3pin_csTb4b4b4, Te6edf3pin_resetTb4b4b4, Te6edf3pin_dioTb4b4b4, Te6edf3pin_busyTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MODEM == SX1262
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setPinsTb4b4b4(Te6edf3pin_csTb4b4b4, Te6edf3pin_resetTb4b4b4, Te6edf3pin_dioTb4b4b4, Te6edf3pin_busyTb4b4b4, Te6edf3pin_rxenTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MODEM == SX1280
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setPinsTb4b4b4(Te6edf3pin_csTb4b4b4, Te6edf3pin_resetTb4b4b4, Te6edf3pin_dioTb4b4b4, Te6edf3pin_busyTb4b4b4, Te6edf3pin_rxenTb4b4b4, Te6edf3pin_txenTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3init_channel_statsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_T3S3
Tff7b72#Tff7b72if MODEM == SX1280
Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_XIAO_S3
T8b949e// Improve wakeup from sleep
Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// Check installed transceiver chip and
T8b949e// probe boot parameters.
Tff7b72if Tb4b4b4(Te6edf3LoRaTff7b72-Tff7b72>Te6edf3preInitTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3modem_installed Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72if HAS_INPUT
T8b949e// Skip quick-reset console activation
Tff7b72#Tff7b72else
Tff7b72uint32_t Te6edf3lfr Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3getFrequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lfr Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
T8b949e// Normal boot
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3lfr Tff7b72=Tff7b72= Te6edf3M_FRQ_RTb4b4b4) Tb4b4b4{
T8b949e// Quick reboot
Tff7b72#Tff7b72if HAS_CONSOLE
Tff7b72if Tb4b4b4(Te6edf3rtc_get_reset_reasonTb4b4b4(T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= Te6edf3POWERON_RESETTb4b4b4) Tb4b4b4{
Te6edf3console_active Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Unknown boot
Tb4b4b4}
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setFrequencyTb4b4b4(Te6edf3M_FRQ_STb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3modem_installed Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
T8b949e// Older variants only came with SX1276/78 chips,
T8b949e// so assume that to be the case for now.
Te6edf3modem_installed Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72#Tff7b72if HAS_EEPROM
Tff7b72if Tb4b4b4(Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DSETTb4b4b4)Tb4b4b4) Tff7b72!Tff7b72= Te6edf3CONF_OK_BYTETb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3eeprom_readTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DSETTb4b4b4)Tb4b4b4) Tff7b72!Tff7b72= Te6edf3CONF_OK_BYTETb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DSETTb4b4b4)Tb4b4b4, Te6edf3CONF_OK_BYTETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TECHO
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DINTTb4b4b4)Tb4b4b4, T79c0ff0x03Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DINTTb4b4b4)Tb4b4b4, T79c0ff0xFFTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_TECHO
Te6edf3display_add_callbackTb4b4b4(Te6edf3work_while_waitingTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3disp_ready Tff7b72= Te6edf3display_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3headless_mode Tff7b72= Tff7b72trueTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Headless] No display detected — running in headless modeTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
T8b949e// LED solid on at boot for V3/V4 boards (with or without display)
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC32_V3
Te6edf3headless_led_solidTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// ── Boundary Mode: check if config portal is needed ──
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
Tb4b4b4{
T8b949e// Load LoRa config from EEPROM so the portal can show current values
Te6edf3eeprom_conf_loadTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Load boundary config so the portal can show current/default values
Te6edf3boundary_load_configTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// ── Bootloop detection ───────────────────────────────────────────────
T8b949e// Track rapid reboots in RTC memory. If the device reboots more than
T8b949e// BOOTLOOP_THRESHOLD times within BOOTLOOP_WINDOW_MS, force the config
T8b949e// portal so the user can fix bad settings.
Tff7b72bool Te6edf3bootloop_detected Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4{
Tff7b72uint32_t Te6edf3now Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3bootloop_magic Tff7b72!Tff7b72= Te6edf3BOOTLOOP_MAGICTb4b4b4) Tb4b4b4{
T8b949e// First boot or power cycle — initialize counter
Te6edf3bootloop_magic Tff7b72= Te6edf3BOOTLOOP_MAGICTb4b4b4;
Te6edf3bootloop_count Tff7b72= T79c0ff1Tb4b4b4;
Te6edf3bootloop_first_boot_ms Tff7b72= Te6edf3nowTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3bootloop_countTff7b72+Tff7b72+Tb4b4b4;
T8b949e// Check if we're within the time window
Tff7b72if Tb4b4b4(Te6edf3bootloop_count Tff7b72>Tff7b72= Te6edf3BOOTLOOP_THRESHOLDTb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] BOOTLOOP DETECTED: %lu reboots — forcing config portalTffea00\rTffea00\nTa5d6ff"Tb4b4b4, Te6edf3bootloop_countTb4b4b4)Tb4b4b4;
Te6edf3bootloop_detected Tff7b72= Tff7b72trueTb4b4b4;
T8b949e// Reset counter so next reboot after config portal doesn't re-trigger
Te6edf3bootloop_count Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3bootloop_magic Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// Enter config mode if: first boot with no config, OR button-triggered reboot,
T8b949e// OR bootloop detected
Tff7b72bool Te6edf3app_marker_missing Tff7b72= Tff7b72!Te6edf3boundary_app_marker_validTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72bool Te6edf3need_config Tff7b72= Te6edf3boundary_needs_configTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72bool Te6edf3config_requested Tff7b72= Tb4b4b4(Te6edf3boundary_config_request Tff7b72=Tff7b72= Te6edf3BOUNDARY_CONFIG_MAGICTb4b4b4)Tb4b4b4;
Tff7b72bool Te6edf3skip_config Tff7b72= Tb4b4b4(Te6edf3boundary_skip_config Tff7b72=Tff7b72= Te6edf3BOUNDARY_SKIP_MAGICTb4b4b4)Tb4b4b4;
Te6edf3boundary_config_request Tff7b72= T79c0ff0Tb4b4b4; T8b949e// Clear flag immediately
Te6edf3boundary_skip_config Tff7b72= T79c0ff0Tb4b4b4; T8b949e// Clear skip flag immediately
T8b949e// Skip flag only suppresses a button-triggered re-entry, not a genuinely
T8b949e// unconfigured device. If there's no config saved, always show the portal.
Tff7b72if Tb4b4b4(Te6edf3skip_config Tff7b72&Tff7b72& Te6edf3config_requestedTb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Skipping config portal — user requested normal bootTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3config_requested Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3need_config Tff7b72|Tff7b72| Te6edf3config_requested Tff7b72|Tff7b72| Te6edf3bootloop_detectedTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bootloop_detectedTb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Entering config portal due to bootloop recoveryTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3config_requestedTb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Config mode requested via button holdTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3app_marker_missingTb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] RTNode app marker missing — previous firmware was not RTNode or config is unclaimedTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Starting config portal to migrate settings into RTNodeTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] No configuration found — starting config portalTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3config_portal_startTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Block here: only run the config portal until user saves and device reboots
T8b949e// Track button state for "off" action (1-3s press = sleep)
Tff7b72bool Te6edf3wcc_btn_down Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72uint32_t Te6edf3wcc_btn_down_at Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3config_portal_is_activeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3config_portal_loopTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Headless LED: slow ramp breathe effect during WCC mode
Te6edf3headless_led_rampTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Button handling: allow 1-3s press to turn off (deep sleep)
T8b949e// Next power-on boots to normal mode since boundary_config_request is cleared
Tff7b72#Tff7b72if HAS_INPUT
Tb4b4b4{
Tff7b72int Te6edf3btn Tff7b72= Td2a8ffdigitalReadTb4b4b4(Te6edf3pin_btn_usr1Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3btn Tff7b72=Tff7b72= Tff7b72LOW Tff7b72&Tff7b72& Tff7b72!Te6edf3wcc_btn_downTb4b4b4) Tb4b4b4{
Te6edf3wcc_btn_down Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3wcc_btn_down_at Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3btn Tff7b72=Tff7b72= Tff7b72HIGH Tff7b72&Tff7b72& Te6edf3wcc_btn_downTb4b4b4) Tb4b4b4{
Tff7b72uint32_t Te6edf3held Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3wcc_btn_down_atTb4b4b4;
Te6edf3wcc_btn_down Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3held Tff7b72>Tff7b72= T79c0ff700 Tff7b72&Tff7b72& Te6edf3held Tff7b72<Tff7b72= T79c0ff5000Tb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Button press in WCC mode — powering offTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3boundary_skip_config Tff7b72= Te6edf3BOUNDARY_SKIP_MAGICTb4b4b4; T8b949e// Skip config on next boot
Te6edf3headless_led_offTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3config_portal_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_SLEEP
Te6edf3sleep_nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Td2a8ffdelayTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// If we exit (shouldn't normally), reboot anyway
Te6edf3ESPTb4b4b4.Te6edf3restartTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72#Tff7b72if HAS_PMU == true
Te6edf3pmu_ready Tff7b72= Te6edf3init_pmuTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72#Tff7b72ifndef BOUNDARY_MODE
Te6edf3bt_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_init_ran Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72else
T8b949e// Boundary mode: release BT controller memory (~70KB)
Te6edf3btStopTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3esp_bt_controller_mem_releaseTb4b4b4(Te6edf3ESP_BT_MODE_BTDMTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72else
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Even when BLE/BT are compile-time disabled (e.g. V3 boundary),
T8b949e// the ESP32 BT controller is still loaded. Release its ~70KB of RAM.
Te6edf3btStopTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3esp_bt_controller_mem_releaseTb4b4b4(Te6edf3ESP_BT_MODE_BTDMTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Released BT controller memoryTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Initialize bt_devname for WiFi hostname when BT is disabled
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3bt_init_ranTb4b4b4)
Tff7b72#Tff7b72endif
Tb4b4b4{
Tff7b72uint8_t Te6edf3macTb4b4b4[T79c0ff6Tb4b4b4]Tb4b4b4;
Te6edf3esp_read_macTb4b4b4(Te6edf3macTb4b4b4, Te6edf3ESP_MAC_WIFI_STATb4b4b4)Tb4b4b4;
Te6edf3sprintfTb4b4b4(Te6edf3bt_devnameTb4b4b4, Ta5d6ff"Ta5d6ffRNode %02X%02XTa5d6ff"Tb4b4b4, Te6edf3macTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Te6edf3macTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3console_activeTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_CONSOLE
Te6edf3console_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3kiss_indicate_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Te6edf3wifi_mode Tff7b72= Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_WIFITb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3wifi_mode Tff7b72=Tff7b72= Te6edf3WR_WIFI_STA Tff7b72|Tff7b72| Te6edf3wifi_mode Tff7b72=Tff7b72= Te6edf3WR_WIFI_APTb4b4b4) Tb4b4b4{ Te6edf3wifi_remote_initTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3kiss_indicate_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72#Tff7b72if MODEM == SX1280
Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72else
Tff7b72#Tff7b72if HAS_EEPROM
Tff7b72uint8_t Te6edf3ia_conf Tff7b72= Td2a8ffEEPROMTb4b4b4.Td2a8ffreadTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DIATb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ia_conf Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Tff7b72uint8_t Te6edf3ia_conf Tff7b72= Te6edf3eeprom_readTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_DIATb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3ia_conf Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3avoid_interference Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
T8b949e// Feed WDT before validation + radio start, which may take time
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// Validate board health, EEPROM and config
Te6edf3validate_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72!Tff7b72= Te6edf3MODE_TNCTb4b4b4) Te6edf3LoRaTff7b72-Tff7b72>Te6edf3setFrequencyTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
T8b949e// CBA SD
Tff7b72#Tff7b72ifdef HAS_SDCARD
Td2a8ffpinModeTb4b4b4(Te6edf3SDCARD_MISOTb4b4b4, Tff7b72INPUT_PULLUPTb4b4b4)Tb4b4b4;
Te6edf3SDSPITb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3SDCARD_SCLKTb4b4b4, Te6edf3SDCARD_MISOTb4b4b4, Te6edf3SDCARD_MOSITb4b4b4, Te6edf3SDCARD_CSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Td2a8ffSDTb4b4b4.Td2a8ffbeginTb4b4b4(Te6edf3SDCARD_CSTb4b4b4, Te6edf3SDSPITb4b4b4)Tb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ffsetupSDCard FAILTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72uint32_t Te6edf3cardSize Tff7b72= Td2a8ffSDTb4b4b4.Te6edf3cardSizeTb4b4b4(Tb4b4b4) Tff7b72/ Tb4b4b4(T79c0ff1024 Tff7b72* T79c0ff1024Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Ta5d6ff"Ta5d6ffsetupSDCard PASS . SIZE = Ta5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Te6edf3cardSize Tff7b72/ T79c0ff1024.0Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff GBTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/logfileTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/logfile.txtTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracefileTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracedetailsTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracefile.txtTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSDTb4b4b4.Td2a8ffremoveTb4b4b4(Ta5d6ff"Ta5d6ff/tracedetails.txtTa5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ffDIR: /Ta5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffFile Te6edf3root Tff7b72= Td2a8ffSDTb4b4b4.Td2a8ffopenTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffFile Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Td2a8ffopenNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72whileTb4b4b4(Te6edf3fileTb4b4b4)Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintTb4b4b4(Ta5d6ff"Ta5d6ff FILE: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Te6edf3fileTb4b4b4.Te6edf3nameTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Td2a8ffopenNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Td2a8ffdelayTb4b4b4(T79c0ff3000Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifdef HAS_RNS
Tff7b72try Tb4b4b4{
T8b949e// Feed WDT before filesystem init (may format on first boot)
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// CBA Init filesystem
Tff7b72#Tff7b72if defined(RNS_USE_FS)
Te6edf3filesystem Tff7b72= Tff7b72new Td2a8ffFileSystemTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4(Tb4b4b4(Td2a8ffFileSystemTff7b72*Tb4b4b4)Te6edf3filesystemTb4b4b4.Td2a8ffgetTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72-Tff7b72>Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3filesystem Tff7b72= Tff7b72new Te6edf3NoopFileSystemTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4(Tb4b4b4(Td2a8ffFileSystemTff7b72*Tb4b4b4)Te6edf3filesystemTb4b4b4.Td2a8ffgetTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72-Tff7b72>Te6edf3initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// Feed WDT after filesystem init
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRegistering filesystem...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3UtilitiesTff7b72:Tff7b72:Te6edf3OSTff7b72:Tff7b72:Te6edf3register_filesystemTb4b4b4(Te6edf3filesystemTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifndef NDEBUG
T8b949e//filesystem.remove_directory("/cache");
T8b949e//filesystem.remove_file("/destination_table");
T8b949e//filesystem.reformat();
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffListing filesystem...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if defined(RNS_USE_FS)
T8b949e//FileSystem::listDir("/");
Tff7b72#Tff7b72endif
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffFinished listingTa5d6ff"Tb4b4b4)Tb4b4b4;
T8b949e//TRACE("Dumping filesystem...");
T8b949e//FileSystem::dumpDir("/");
T8b949e//TRACE("Finished dumping");
T8b949e//reticulum.clear_caches();
T8b949e// CBA DEBUG
T8b949e/*
std::list<std::string> files = filesystem.list_directory("/cache");
for (auto& file : files) {
Serial.print(" FILE: ");
Serial.println(file.c_str());
//RNS::Bytes content = filesystem.read_file(file.c_str());
//DEBUG(std::string("FILE: ") + file);
//DEBUG(content.toString());
}
*/
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffFILE: destination_tableTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Bytes Te6edf3contentTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3filesystemTb4b4b4.Te6edf3read_fileTb4b4b4(Ta5d6ff"Ta5d6ff/destination_tableTa5d6ff"Tb4b4b4, Te6edf3contentTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3TRACETb4b4b4(Te6edf3contentTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// NDEBUG
T8b949e// CBA Start RNS
Tff7b72if Tb4b4b4(Te6edf3hw_readyTb4b4b4) Tb4b4b4{
T8b949e// Feed WDT before RNS startup (identity generation + crypto can be slow)
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3RNSTff7b72:Tff7b72:Te6edf3setLogCallbackTb4b4b4(Tff7b72&Te6edf3on_logTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3set_receive_packet_callbackTb4b4b4(Te6edf3on_receive_packetTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3set_transmit_packet_callbackTb4b4b4(Te6edf3on_transmit_packetTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffStarting RNS...Tffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3loglevelTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_VERBOSETb4b4b4)Tb4b4b4;
T8b949e//RNS::loglevel(RNS::LOG_TRACE);
T8b949e//RNS::loglevel(RNS::LOG_MEM);
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRegistering LoRA Interface...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3lora_interface Tff7b72= Tff7b72new Te6edf3LoRaInterfaceTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3lora_interfaceTb4b4b4.Te6edf3modeTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3InterfaceTff7b72:Tff7b72:Te6edf3MODE_ACCESS_POINTTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3register_interfaceTb4b4b4(Te6edf3lora_interfaceTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// ── Boundary Mode: Load config and optionally set up WiFi + TCP ──
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffBoundary Mode: Initializing...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
T8b949e// ESP32 has only ~324KB heap. Each path entry with random_blobs costs
T8b949e// ~200-500 bytes. Keep tables small to avoid heap exhaustion.
T8b949e// cull_path_table() evicts backbone paths first, preserving local ones.
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_table_maxsizeTb4b4b4(T79c0ff24Tb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3path_table_maxpersistTb4b4b4(T79c0ff12Tb4b4b4)Tb4b4b4;
Te6edf3boundary_load_configTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Set up IFAC on the LoRa interface if configured
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_enabled Tff7b72&Tff7b72&
Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_netnameTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72!Tff7b72= Ta5d6ff'Ta5d6ff\0Ta5d6ff' Tff7b72|Tff7b72| Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_passphraseTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72!Tff7b72= Ta5d6ff'Ta5d6ff\0Ta5d6ff'Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffSetting up IFAC on LoRa interface...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3lora_interfaceTb4b4b4.Te6edf3setup_ifacTb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_netnameTb4b4b4, Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_passphraseTb4b4b4)Tb4b4b4;
Tb4b4b4{
Tff7b72char Te6edf3_ifac_msgTb4b4b4[T79c0ff96Tb4b4b4]Tb4b4b4;
Te6edf3snprintfTb4b4b4(Te6edf3_ifac_msgTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_ifac_msgTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffIFAC configured: netname=%s, passphrase=%sTa5d6ff"Tb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_netnameTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72? Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_netname Tff7b72: Ta5d6ff"Ta5d6ff(none)Ta5d6ff"Tb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3ifac_passphraseTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72? Ta5d6ff"Ta5d6ff***Ta5d6ff" Tff7b72: Ta5d6ff"Ta5d6ff(none)Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Te6edf3_ifac_msgTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Start WiFi if enabled
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_enabledTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3wifi_initializedTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3wifi_mode Tff7b72!Tff7b72= Te6edf3WR_WIFI_STA Tff7b72&Tff7b72& Te6edf3wifi_mode Tff7b72!Tff7b72= Te6edf3WR_WIFI_APTb4b4b4) Tb4b4b4{
Te6edf3wifi_mode Tff7b72= Te6edf3WR_WIFI_STATb4b4b4;
Td2a8ffEEPROMTb4b4b4.Td2a8ffwriteTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_WIFITb4b4b4)Tb4b4b4, Te6edf3wifi_modeTb4b4b4)Tb4b4b4;
Td2a8ffEEPROMTb4b4b4.Te6edf3commitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3wifi_remote_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffBoundary Mode: WiFi DISABLED (LoRa-only repeater)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Register TCP backbone interface if enabled (mode 1 = client)
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_enabled Tff7b72&Tff7b72& Te6edf3boundary_stateTb4b4b4.Te6edf3tcp_mode Tff7b72=Tff7b72= T79c0ff1Tb4b4b4) Tb4b4b4{
Te6edf3tcp_interface_ptr Tff7b72= Tff7b72new Te6edf3TcpInterfaceTb4b4b4(
Te6edf3TCP_IF_MODE_CLIENTTb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3tcp_portTb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3backbone_hostTb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3backbone_port
Tb4b4b4)Tb4b4b4;
Te6edf3tcp_rns_interface Tff7b72= Te6edf3tcp_interface_ptrTb4b4b4;
Te6edf3tcp_rns_interfaceTb4b4b4.Te6edf3modeTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3InterfaceTff7b72:Tff7b72:Te6edf3MODE_BOUNDARYTb4b4b4)Tb4b4b4;
Te6edf3tcp_rns_interfaceTb4b4b4.Te6edf3is_backboneTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3register_interfaceTb4b4b4(Te6edf3tcp_rns_interfaceTb4b4b4)Tb4b4b4;
Tb4b4b4{
Tff7b72char Te6edf3_bm_msgTb4b4b4[T79c0ff128Tb4b4b4]Tb4b4b4;
Te6edf3snprintfTb4b4b4(Te6edf3_bm_msgTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_bm_msgTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffTCP backbone: client -> %s:%dTa5d6ff"Tb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3backbone_hostTb4b4b4, Te6edf3boundary_stateTb4b4b4.Te6edf3backbone_portTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Te6edf3_bm_msgTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3tcp_mode Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffBoundary Mode: TCP backbone DISABLEDTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Register local TCP server if enabled
T8b949e// MODE_GATEWAY allows announce rebroadcasts so local TCP clients
T8b949e// can discover each other and receive backbone announces.
T8b949e// (MODE_ACCESS_POINT blocks all announce broadcasts in outbound(),
T8b949e// which prevented local clients from finding paths to each other.)
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_enabled Tff7b72&Tff7b72& Te6edf3boundary_stateTb4b4b4.Te6edf3ap_tcp_enabledTb4b4b4) Tb4b4b4{
Te6edf3local_tcp_interface_ptr Tff7b72= Tff7b72new Te6edf3TcpInterfaceTb4b4b4(
Te6edf3TCP_IF_MODE_SERVERTb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3ap_tcp_portTb4b4b4,
Ta5d6ff"Ta5d6ff"Tb4b4b4, T8b949e// no target host for server mode
T79c0ff0Tb4b4b4,
Ta5d6ff"Ta5d6ffLocalTcpInterfaceTa5d6ff"
Tb4b4b4)Tb4b4b4;
T8b949e// rnsd can be quiet for long stretches — use 10 min timeout
T8b949e// to prevent unnecessary reconnection cycles that leak lwIP memory
Te6edf3local_tcp_interface_ptrTff7b72-Tff7b72>Te6edf3setReadTimeoutTb4b4b4(T79c0ff600000Tb4b4b4)Tb4b4b4;
Te6edf3local_tcp_rns_interface Tff7b72= Te6edf3local_tcp_interface_ptrTb4b4b4;
Te6edf3local_tcp_rns_interfaceTb4b4b4.Te6edf3modeTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3InterfaceTff7b72:Tff7b72:Te6edf3MODE_GATEWAYTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3register_interfaceTb4b4b4(Te6edf3local_tcp_rns_interfaceTb4b4b4)Tb4b4b4;
T8b949e// Register as local client interface so Transport forwards
T8b949e// announces, link packets, and proofs to TCP clients
Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3register_local_client_interfaceTb4b4b4(Te6edf3local_tcp_rns_interfaceTb4b4b4)Tb4b4b4;
Tb4b4b4{
Tff7b72char Te6edf3_bm_msgTb4b4b4[T79c0ff128Tb4b4b4]Tb4b4b4;
Te6edf3snprintfTb4b4b4(Te6edf3_bm_msgTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_bm_msgTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffLocal TCP server: port %d (GATEWAY mode)Ta5d6ff"Tb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3ap_tcp_portTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Te6edf3_bm_msgTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
T8b949e// Feed WDT before Reticulum instance creation (loads caches, generates keys)
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffCreating Reticulum instance...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3reticulum Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3ReticulumTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// In boundary mode, transport is ALWAYS enabled
Te6edf3reticulumTb4b4b4.Te6edf3transport_enabledTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3reticulumTb4b4b4.Te6edf3transport_enabledTb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_TNCTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3reticulumTb4b4b4.Te6edf3probe_destination_enabledTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Te6edf3reticulumTb4b4b4.Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Start TCP interfaces after Reticulum is running
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_enabled Tff7b72&Tff7b72& Tb4b4b4(Te6edf3wifi_is_connectedTb4b4b4(Tb4b4b4) Tff7b72|Tff7b72| Te6edf3wifi_mode Tff7b72=Tff7b72= Te6edf3WR_WIFI_APTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3tcp_interface_ptrTb4b4b4) Tb4b4b4{
Te6edf3tcp_interface_ptrTff7b72-Tff7b72>Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffBoundary Mode: TCP backbone startedTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3local_tcp_interface_ptrTb4b4b4) Tb4b4b4{
Te6edf3local_tcp_interface_ptrTff7b72-Tff7b72>Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffBoundary Mode: Local TCP server startedTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_enabledTb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffBoundary Mode: Waiting for WiFi before starting TCP interfacesTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_WARNINGTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
T8b949e// CBA load/create local destination for admin node
T8b949e/*
RNS::Identity identity = {RNS::Type::NONE};
std::string local_identity_path = RNS::Reticulum::_storagepath + "/local_identity";
if (RNS::Utilities::OS::file_exists(local_identity_path.c_str())) {
identity = RNS::Identity::from_file(local_identity_path.c_str());
}
if (!identity) {
RNS::verbose("No valid local identity in storage, creating...");
identity = RNS::Identity();
identity.to_file(local_identity_path.c_str());
}
else {
RNS::verbose("Loaded local identity from storage");
}
RNS::Destination destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "rnstransport", "local");
*/
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Destination Te6edf3destinationTb4b4b4(Te6edf3RNSTff7b72:Tff7b72:Te6edf3TransportTff7b72:Tff7b72:Te6edf3identityTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3INTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3DestinationTff7b72:Tff7b72:Te6edf3SINGLETb4b4b4, Ta5d6ff"Ta5d6ffrnstransportTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflocalTa5d6ff"Tb4b4b4)Tb4b4b4;
T8b949e// Cache this node's destination hash in RTC memory so the captive-portal
T8b949e// config page can show it without needing RNS to be running.
Tb4b4b4{
Te6edf3stdTff7b72:Tff7b72:Tff7b72string Te6edf3h Tff7b72= Te6edf3destinationTb4b4b4.Te6edf3hashTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toHexTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657size_t Te6edf3len Tff7b72= Te6edf3hTb4b4b4.Te6edf3lengthTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3len Tff7b72> T79c0ff32Tb4b4b4) Te6edf3len Tff7b72= T79c0ff32Tb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3rtc_node_hash_hexTb4b4b4, Te6edf3hTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3rtc_node_hash_hexTb4b4b4[Te6edf3lenTb4b4b4] Tff7b72= Ta5d6ff'Ta5d6ff\0Ta5d6ff'Tb4b4b4;
Te6edf3rtc_node_hash_magic Tff7b72= Te6edf3NODE_HASH_RTC_MAGICTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Initialise the Reticulum interface-discovery announcer. Per the
T8b949e// Reticulum manual (https://reticulum.network/manual/interfaces.html)
T8b949e// this announces this node and its parameters on the network so that
T8b949e// maps such as rmap.world can automatically place a pin for it. The
T8b949e// announcer is a no-op until the user has enabled "Advertise Device"
T8b949e// in the captive-portal configuration.
Te6edf3advertise_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS is READY!Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ff*** BOUNDARY MODE ACTIVE ***Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS transport mode is ENABLED (boundary)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffLoRa Interface: MODE_ACCESS_POINTTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4{
Tff7b72char Te6edf3_bm_infoTb4b4b4[T79c0ff128Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3tcp_mode Tff7b72=Tff7b72= T79c0ff1Tb4b4b4) Tb4b4b4{
Te6edf3snprintfTb4b4b4(Te6edf3_bm_infoTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_bm_infoTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffTCP Backbone: client -> %s:%dTa5d6ff"Tb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3backbone_hostTb4b4b4, Te6edf3boundary_stateTb4b4b4.Te6edf3backbone_portTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Te6edf3_bm_infoTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffTCP Backbone: DISABLEDTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3ap_tcp_enabledTb4b4b4) Tb4b4b4{
Te6edf3snprintfTb4b4b4(Te6edf3_bm_infoTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3_bm_infoTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffLocal TCP Server: port %d (MODE_ACCESS_POINT)Ta5d6ff"Tb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3ap_tcp_portTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Te6edf3_bm_infoTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_enabledTb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffWiFi: DISABLED (LoRa-only repeater)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_TNCTb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS transport mode is ENABLEDTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_TRACETb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffFrequency: %d HzTa5d6ff"Tb4b4b4, Te6edf3lora_freqTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffBandwidth: %d HzTa5d6ff"Tb4b4b4, Te6edf3lora_bwTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffTX Power: %d dBmTa5d6ff"Tb4b4b4, Te6edf3lora_txpTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffSpreading Factor: %dTa5d6ff"Tb4b4b4, Te6edf3lora_sfTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffCoding Rate: %dTa5d6ff"Tb4b4b4, Te6edf3lora_crTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS transport mode is DISABLEDTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_INFOTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffConfigure TNC mode with radio configuration to enable RNS transportTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_INFOTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e//RNS::loglevel(RNS::LOG_NONE);
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffRNS is inoperable because hardware is not ready!Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_ERRORTb4b4b4)Tb4b4b4;
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffCheck firmware signature and eeprom provisioningTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_ERRORTb4b4b4)Tb4b4b4;
T8b949e// CBA Clear cached files just in case cached files are responsible for failure
T8b949e//reticulum.clear_caches();
Tb4b4b4}
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffRNS startup failed: Ta5d6ff" Tff7b72+ Te6edf3stdTff7b72:Tff7b72:Tff7b72stringTb4b4b4(Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// HAS_RNS
Tb4b4b4}
Tff7b72void Te6edf3lora_receiveTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3implicitTb4b4b4) Tb4b4b4{
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3receiveTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3receiveTb4b4b4(Te6edf3implicit_lTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72inline Tff7b72void Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef HAS_RNS
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffReceived %d byte packetTa5d6ff"Tb4b4b4, Te6edf3host_write_lenTb4b4b4)Tb4b4b4;
T8b949e// CBA send packet received over LoRa to RNS in addition to connected client
T8b949e// CBA RESERVE
T8b949e//RNS::Bytes data();
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Bytes Te6edf3dataTb4b4b4(T79c0ff512Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3host_write_lenTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3portENTER_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint8_t Tff7b72byte Tff7b72= Te6edf3pbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Te6edf3portEXIT_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72uint8_t Tff7b72byte Tff7b72= Te6edf3pbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3data Tff7b72<Tff7b72< Tff7b72byteTb4b4b4;
Tb4b4b4}
Te6edf3lora_interfaceTb4b4b4.Te6edf3handle_incomingTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3serial_writeTb4b4b4(Te6edf3FENDTb4b4b4)Tb4b4b4;
Te6edf3serial_writeTb4b4b4(Te6edf3CMD_DATATb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3host_write_lenTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3portENTER_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint8_t Tff7b72byte Tff7b72= Te6edf3pbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Te6edf3portEXIT_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72uint8_t Tff7b72byte Tff7b72= Te6edf3pbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Tff7b72byte Tff7b72=Tff7b72= Te6edf3FENDTb4b4b4) Tb4b4b4{ Te6edf3serial_writeTb4b4b4(Te6edf3FESCTb4b4b4)Tb4b4b4; Tff7b72byte Tff7b72= Te6edf3TFENDTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72byte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3serial_writeTb4b4b4(Te6edf3FESCTb4b4b4)Tb4b4b4; Tff7b72byte Tff7b72= Te6edf3TFESCTb4b4b4; Tb4b4b4}
Te6edf3serial_writeTb4b4b4(Tff7b72byteTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3serial_writeTb4b4b4(Te6edf3FENDTb4b4b4)Tb4b4b4;
Te6edf3host_write_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3packet_ready Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Tff7b72#Tff7b72if HAS_BLE
Te6edf3bt_flushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72inline Tff7b72void Te6edf3getPacketDataTb4b4b4(Tff7b72uint16_t Te6edf3lenTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT != MCU_NRF52
Tff7b72while Tb4b4b4(Te6edf3lenTff7b72-Tff7b72- Tff7b72&Tff7b72& Te6edf3read_len Tff7b72< Te6edf3MTUTb4b4b4) Tb4b4b4{
Te6edf3pbufTb4b4b4[Te6edf3read_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3BaseType_t Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3lenTff7b72-Tff7b72- Tff7b72&Tff7b72& Te6edf3read_len Tff7b72< Te6edf3MTUTb4b4b4) Tb4b4b4{
Te6edf3pbufTb4b4b4[Te6edf3read_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72void Te6edf3ISR_VECT Te6edf3receive_callbackTb4b4b4(Tff7b72int Te6edf3packet_sizeTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3BaseType_t Te6edf3int_maskTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3promiscTb4b4b4) Tb4b4b4{
T8b949e// The standard operating mode allows large
T8b949e// packets with a payload up to 500 bytes,
T8b949e// by combining two raw LoRa packets.
T8b949e// We read the 1-byte header and extract
T8b949e// packet sequence number and split flags
Tff7b72uint8_t Te6edf3header Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3packet_sizeTff7b72-Tff7b72-Tb4b4b4;
Tff7b72uint8_t Te6edf3sequence Tff7b72= Te6edf3packetSequenceTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4;
Tff7b72bool Td2a8ffready Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4) Tff7b72&Tff7b72& Te6edf3seq Tff7b72=Tff7b72= Te6edf3SEQ_UNSETTb4b4b4) Tb4b4b4{
T8b949e// This is the first part of a split
T8b949e// packet, so we set the seq variable
T8b949e// and add the data to the buffer
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4; Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3seq Tff7b72= Te6edf3sequenceTb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4) Tff7b72&Tff7b72& Te6edf3seq Tff7b72=Tff7b72= Te6edf3sequenceTb4b4b4) Tb4b4b4{
T8b949e// This is the second part of a split
T8b949e// packet, so we add it to the buffer
T8b949e// and set the ready flag.
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Te6edf3last_rssi Tff7b72= Tb4b4b4(Te6edf3last_rssiTff7b72+Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72/T79c0ff2Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Tb4b4b4(Te6edf3last_snr_rawTff7b72+Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72/T79c0ff2Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Te6edf3seq Tff7b72= Te6edf3SEQ_UNSETTb4b4b4;
Td2a8ffready Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4) Tff7b72&Tff7b72& Te6edf3seq Tff7b72!Tff7b72= Te6edf3sequenceTb4b4b4) Tb4b4b4{
T8b949e// This split packet does not carry the
T8b949e// same sequence id, so we must assume
T8b949e// that we are seeing the first part of
T8b949e// a new split packet.
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4; Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3seq Tff7b72= Te6edf3sequenceTb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// This is not a split packet, so we
T8b949e// just read it and set the ready
T8b949e// flag to true.
Tff7b72if Tb4b4b4(Te6edf3seq Tff7b72!Tff7b72= Te6edf3SEQ_UNSETTb4b4b4) Tb4b4b4{
T8b949e// If we already had part of a split
T8b949e// packet in the buffer, we clear it.
Tff7b72#Tff7b72if MCU_VARIANT == MCU_NRF52
Te6edf3int_mask Tff7b72= Te6edf3taskENTER_CRITICAL_FROM_ISRTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4; Te6edf3taskEXIT_CRITICAL_FROM_ISRTb4b4b4(Te6edf3int_maskTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3seq Tff7b72= Te6edf3SEQ_UNSETTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Td2a8ffready Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Td2a8ffreadyTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
T8b949e// We first signal the RSSI of the
T8b949e// recieved packet to the host.
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// And then write the entire packet
Te6edf3host_write_len Tff7b72= Te6edf3read_lenTb4b4b4;
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72else
T8b949e// Allocate packet struct, but abort if there
T8b949e// is not enough memory available.
Te6edf3modem_packet_t Tff7b72*Te6edf3modem_packet Tff7b72= Tb4b4b4(Te6edf3modem_packet_tTff7b72*Tb4b4b4)Te6edf3mallocTb4b4b4(Tff7b72sizeofTb4b4b4(Te6edf3modem_packet_tTb4b4b4) Tff7b72+ Te6edf3read_lenTb4b4b4)Tb4b4b4;
Tff7b72ifTb4b4b4(Tff7b72!Te6edf3modem_packetTb4b4b4) Tb4b4b4{ Te6edf3memory_low Tff7b72= Tff7b72trueTb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4}
T8b949e// Get packet RSSI and SNR
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3snr_rawTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// Send packet to event queue, but free the
T8b949e// allocated memory again if the queue is
T8b949e// unable to receive the packet.
Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3len Tff7b72= Te6edf3read_lenTb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3dataTb4b4b4, Te6edf3pbufTb4b4b4, Te6edf3read_lenTb4b4b4)Tb4b4b4; Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3modem_packet_queue Tff7b72|Tff7b72| Te6edf3xQueueSendFromISRTb4b4b4(Te6edf3modem_packet_queueTb4b4b4, Tff7b72&Te6edf3modem_packetTb4b4b4, Tffa657NULLTb4b4b4) Tff7b72!Tff7b72= Te6edf3pdPASSTb4b4b4) Tb4b4b4{
Te6edf3freeTb4b4b4(Te6edf3modem_packetTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// In promiscuous mode, raw packets are
T8b949e// output directly to the host
Te6edf3read_len Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
T8b949e// We first signal the RSSI of the
T8b949e// recieved packet to the host.
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// And then write the entire packet
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Te6edf3getPacketDataTb4b4b4(Te6edf3packet_sizeTb4b4b4)Tb4b4b4;
Te6edf3packet_ready Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tff7b72bool Te6edf3startRadioTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3update_radio_lockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3radio_online Tff7b72&Tff7b72& Tff7b72!Te6edf3console_activeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3radio_locked Tff7b72&Tff7b72& Te6edf3hw_readyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginTb4b4b4(Te6edf3lora_freqTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// The radio could not be started.
T8b949e// Indicate this failure over both the
T8b949e// serial port and with the onboard LEDs
Te6edf3radio_error Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_INITRADIOTb4b4b4)Tb4b4b4;
Te6edf3led_indicate_errorTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3radio_online Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3init_channel_statsTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setTXPowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setBandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setSpreadingFactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3setCodingRateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3getFrequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3enableCrcTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffonReceiveTb4b4b4(Te6edf3receive_callbackTb4b4b4)Tb4b4b4;
Te6edf3lora_receiveTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Flash an info pattern to indicate
T8b949e// that the radio is now on
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3led_indicate_infoTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Flash a warning pattern to indicate
T8b949e// that the radio was locked, and thus
T8b949e// not started
Te6edf3radio_online Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3led_indicate_warningTb4b4b4(T79c0ff3Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// If radio is already on, we silently
T8b949e// ignore the request.
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72void Te6edf3stopRadioTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3radio_online Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72void Te6edf3update_radio_lockTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3lora_freq Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3lora_bw Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3lora_txp Tff7b72!Tff7b72= T79c0ff0xFF Tff7b72&Tff7b72& Te6edf3lora_sf Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3radio_locked Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3radio_locked Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72bool Te6edf3queue_fullTb4b4b4(Tb4b4b4) Tb4b4b4{ Tff7b72return Tb4b4b4(Te6edf3queue_height Tff7b72>Tff7b72= Te6edf3CONFIG_QUEUE_MAX_LENGTH Tff7b72|Tff7b72| Te6edf3queued_bytes Tff7b72>Tff7b72= Te6edf3CONFIG_QUEUE_SIZETb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72volatile Tff7b72bool Te6edf3queue_flushing Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72void Te6edf3flush_queueTb4b4b4(Tff7b72voidTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3queue_flushingTb4b4b4) Tb4b4b4{
Te6edf3queue_flushing Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3led_tx_onTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo16_isemptyTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo16_isempty_lockedTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tff7b72uint16_t Te6edf3start Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3length Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3length Tff7b72>Tff7b72= Te6edf3MIN_L Tff7b72&Tff7b72& Te6edf3length Tff7b72<Tff7b72= Te6edf3MTUTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3lengthTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3pos Tff7b72= Tb4b4b4(Te6edf3startTff7b72+Te6edf3iTb4b4b4)Tff7b72%Te6edf3CONFIG_QUEUE_SIZETb4b4b4;
Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3packet_queueTb4b4b4[Te6edf3posTb4b4b4]Tb4b4b4;
Tb4b4b4}
Te6edf3transmitTb4b4b4(Te6edf3lengthTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Te6edf3lora_receiveTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3led_tx_offTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3queue_height Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3queued_bytes Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3update_airtimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3queue_flushing Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Te6edf3display_tx Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72void Te6edf3pop_queueTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3queue_flushingTb4b4b4) Tb4b4b4{
Te6edf3queue_flushing Tff7b72= Tff7b72trueTb4b4b4; Te6edf3led_tx_onTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo16_isemptyTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo16_isempty_lockedTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tff7b72uint16_t Te6edf3start Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3length Tff7b72= Te6edf3fifo16_popTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3length Tff7b72>Tff7b72= Te6edf3MIN_L Tff7b72&Tff7b72& Te6edf3length Tff7b72<Tff7b72= Te6edf3MTUTb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Te6edf3lengthTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3pos Tff7b72= Tb4b4b4(Te6edf3startTff7b72+Te6edf3iTb4b4b4)Tff7b72%Te6edf3CONFIG_QUEUE_SIZETb4b4b4;
Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4] Tff7b72= Te6edf3packet_queueTb4b4b4[Te6edf3posTb4b4b4]Tb4b4b4;
Tb4b4b4}
Te6edf3transmitTb4b4b4(Te6edf3lengthTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3queue_height Tff7b72-Tff7b72= T79c0ff1Tb4b4b4;
Te6edf3queued_bytes Tff7b72-Tff7b72= Te6edf3lengthTb4b4b4;
Tb4b4b4}
Te6edf3lora_receiveTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3led_tx_offTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3update_airtimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3queue_flushing Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Te6edf3display_tx Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72void Te6edf3add_airtimeTb4b4b4(Tff7b72uint16_t Te6edf3writtenTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72float Te6edf3lora_symbols Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72float Te6edf3packet_cost_ms Tff7b72= T79c0ff0.0Tb4b4b4;
Tff7b72int Te6edf3ldr_opt Tff7b72= T79c0ff0Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3lora_low_datarateTb4b4b4) Te6edf3ldr_opt Tff7b72= T79c0ff1Tb4b4b4;
Tff7b72#Tff7b72if MODEM == SX1276 || MODEM == SX1278
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ T79c0ff8 Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Tb4b4b4(Te6edf3lora_sfT79c0ff-2Tff7b72*Te6edf3ldr_optTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff0.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;
Tff7b72#Tff7b72elif MODEM == SX1262 || MODEM == SX1280
Tff7b72if Tb4b4b4(Te6edf3lora_sf Tff7b72< T79c0ff7Tb4b4b4) Tb4b4b4{
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Te6edf3lora_sfTb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff2.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lora_symbols Tff7b72+Tff7b72= Tb4b4b4(T79c0ff8Tff7b72*Te6edf3written Tff7b72+ Te6edf3PHY_CRC_LORA_BITS Tff7b72- T79c0ff4Tff7b72*Te6edf3lora_sf Tff7b72+ T79c0ff8 Tff7b72+ Te6edf3PHY_HEADER_LORA_SYMBOLSTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72/Tff7b72= T79c0ff4Tff7b72*Tb4b4b4(Te6edf3lora_sfT79c0ff-2Tff7b72*Te6edf3ldr_optTb4b4b4)Tb4b4b4;
Te6edf3lora_symbols Tff7b72*Tff7b72= Te6edf3lora_crTb4b4b4;
Te6edf3lora_symbols Tff7b72+Tff7b72= Te6edf3lora_preamble_symbols Tff7b72+ T79c0ff0.25 Tff7b72+ T79c0ff8Tb4b4b4;
Te6edf3packet_cost_ms Tff7b72+Tff7b72= Te6edf3lora_symbols Tff7b72* Te6edf3lora_symbol_time_msTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72uint16_t Te6edf3cb Tff7b72= Te6edf3current_airtime_binTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3nb Tff7b72= Te6edf3cbTff7b72+T79c0ff1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3nb Tff7b72=Tff7b72= Te6edf3AIRTIME_BINSTb4b4b4) Tb4b4b4{ Te6edf3nb Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4}
Te6edf3airtime_binsTb4b4b4[Te6edf3cbTb4b4b4] Tff7b72+Tff7b72= Te6edf3packet_cost_msTb4b4b4;
Te6edf3airtime_binsTb4b4b4[Te6edf3nbTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72void Te6edf3update_airtimeTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72uint16_t Te6edf3cb Tff7b72= Te6edf3current_airtime_binTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3pb Tff7b72= Te6edf3cbT79c0ff-1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3cbT79c0ff-1 Tff7b72< T79c0ff0Tb4b4b4) Tb4b4b4{ Te6edf3pb Tff7b72= Te6edf3AIRTIME_BINST79c0ff-1Tb4b4b4; Tb4b4b4}
Tff7b72uint16_t Te6edf3nb Tff7b72= Te6edf3cbTff7b72+T79c0ff1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3nb Tff7b72=Tff7b72= Te6edf3AIRTIME_BINSTb4b4b4) Tb4b4b4{ Te6edf3nb Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4}
Te6edf3airtime_binsTb4b4b4[Te6edf3nbTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4; Te6edf3airtime Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Tb4b4b4(Te6edf3airtime_binsTb4b4b4[Te6edf3cbTb4b4b4]Tff7b72+Te6edf3airtime_binsTb4b4b4[Te6edf3pbTb4b4b4]Tb4b4b4)Tff7b72/Tb4b4b4(T79c0ff2.0Tff7b72*Te6edf3AIRTIME_BINLEN_MSTb4b4b4)Tb4b4b4;
Tff7b72uint32_t Te6edf3longterm_airtime_sum Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3bin Tff7b72= T79c0ff0Tb4b4b4; Te6edf3bin Tff7b72< Te6edf3AIRTIME_BINSTb4b4b4; Te6edf3binTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3longterm_airtime_sum Tff7b72+Tff7b72= Te6edf3airtime_binsTb4b4b4[Te6edf3binTb4b4b4]Tb4b4b4; Tb4b4b4}
Te6edf3longterm_airtime Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3longterm_airtime_sumTff7b72/Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3AIRTIME_LONGTERM_MSTb4b4b4;
Tff7b72float Te6edf3longterm_channel_util_sum Tff7b72= T79c0ff0.0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3bin Tff7b72= T79c0ff0Tb4b4b4; Te6edf3bin Tff7b72< Te6edf3AIRTIME_BINSTb4b4b4; Te6edf3binTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3longterm_channel_util_sum Tff7b72+Tff7b72= Te6edf3longterm_binsTb4b4b4[Te6edf3binTb4b4b4]Tb4b4b4; Tb4b4b4}
Te6edf3longterm_channel_util Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3longterm_channel_util_sumTff7b72/Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3AIRTIME_BINSTb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3update_csma_parametersTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3kiss_indicate_channel_statsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72void Te6edf3transmitTb4b4b4(Tff7b72uint16_t Td2a8ffsizeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3radio_onlineTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3promiscTb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3written Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72uint8_t Te6edf3header Tff7b72= Td2a8ffrandomTb4b4b4(T79c0ff256Tb4b4b4) Tff7b72& T79c0ff0xF0Tb4b4b4;
Tff7b72if Tb4b4b4(Td2a8ffsize Tff7b72> Te6edf3SINGLE_MTU Tff7b72- Te6edf3HEADER_LTb4b4b4) Tb4b4b4{ Te6edf3header Tff7b72= Te6edf3header Tff7b72| Te6edf3FLAG_SPLITTb4b4b4; Tb4b4b4}
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4; Te6edf3writtenTff7b72+Tff7b72+Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3iTff7b72=T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Td2a8ffsizeTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Te6edf3writtenTff7b72+Tff7b72+Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3written Tff7b72=Tff7b72= T79c0ff255 Tff7b72&Tff7b72& Te6edf3isSplitPacketTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendPacketTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MODEM_TIMEOUTTb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_TXFAILEDTb4b4b4)Tb4b4b4;
Te6edf3led_indicate_errorTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4;
Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3add_airtimeTb4b4b4(Te6edf3writtenTb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3headerTb4b4b4)Tb4b4b4;
Te6edf3written Tff7b72= T79c0ff1Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendPacketTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MODEM_TIMEOUTTb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_TXFAILEDTb4b4b4)Tb4b4b4;
Te6edf3led_indicate_errorTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4;
Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3add_airtimeTb4b4b4(Te6edf3writtenTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3led_tx_onTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72uint16_t Te6edf3written Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72if Tb4b4b4(Td2a8ffsize Tff7b72> Te6edf3SINGLE_MTUTb4b4b4) Tb4b4b4{ Td2a8ffsize Tff7b72= Te6edf3SINGLE_MTUTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3implicitTb4b4b4) Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffbeginPacketTb4b4b4(Td2a8ffsizeTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72for Tb4b4b4(Tff7b72uint16_t Te6edf3iTff7b72=T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< Td2a8ffsizeTb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffwriteTb4b4b4(Te6edf3tbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Te6edf3writtenTff7b72+Tff7b72+Tb4b4b4; Tb4b4b4}
Te6edf3LoRaTff7b72-Tff7b72>Td2a8ffendPacketTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3add_airtimeTb4b4b4(Te6edf3writtenTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_TXFAILEDTb4b4b4)Tb4b4b4; Te6edf3led_indicate_errorTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tff7b72void Te6edf3serial_callbackTb4b4b4(Tff7b72uint8_t Te6edf3sbyteTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3IN_FRAME Tff7b72&Tff7b72& Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FEND Tff7b72&Tff7b72& Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DATATb4b4b4) Tb4b4b4{
Te6edf3IN_FRAME Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo16_isfullTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4) Tff7b72&Tff7b72& Te6edf3queued_bytes Tff7b72< Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3s Tff7b72= Te6edf3current_packet_startTb4b4b4;
Tff7b72int16_t Te6edf3e Tff7b72= Te6edf3queue_cursorT79c0ff-1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3e Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Te6edf3e Tff7b72= Te6edf3CONFIG_QUEUE_SIZET79c0ff-1Tb4b4b4;
Tff7b72uint16_t Te6edf3lTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3s Tff7b72!Tff7b72= Te6edf3eTb4b4b4) Tb4b4b4{ Te6edf3l Tff7b72= Tb4b4b4(Te6edf3s Tff7b72< Te6edf3eTb4b4b4) Tff7b72? Te6edf3e Tff7b72- Te6edf3s Tff7b72+ T79c0ff1 Tff7b72: Te6edf3CONFIG_QUEUE_SIZE Tff7b72- Te6edf3s Tff7b72+ Te6edf3e Tff7b72+ T79c0ff1Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3l Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3l Tff7b72>Tff7b72= Te6edf3MIN_LTb4b4b4) Tb4b4b4{
Te6edf3queue_heightTff7b72+Tff7b72+Tb4b4b4;
Te6edf3fifo16_pushTb4b4b4(Tff7b72&Te6edf3packet_startsTb4b4b4, Te6edf3sTb4b4b4)Tb4b4b4;
Te6edf3fifo16_pushTb4b4b4(Tff7b72&Te6edf3packet_lengthsTb4b4b4, Te6edf3lTb4b4b4)Tb4b4b4;
Te6edf3current_packet_start Tff7b72= Te6edf3queue_cursorTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FENDTb4b4b4) Tb4b4b4{
Te6edf3IN_FRAME Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3command Tff7b72= Te6edf3CMD_UNKNOWNTb4b4b4;
Te6edf3frame_len Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3IN_FRAME Tff7b72&Tff7b72& Te6edf3frame_len Tff7b72< Te6edf3MTUTb4b4b4) Tb4b4b4{
T8b949e// Have a look at the command byte first
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_UNKNOWNTb4b4b4) Tb4b4b4{
Te6edf3command Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DATATb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_CONNECTEDTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3queue_height Tff7b72< Te6edf3CONFIG_QUEUE_MAX_LENGTH Tff7b72&Tff7b72& Te6edf3queued_bytes Tff7b72< Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Tb4b4b4{
Te6edf3queued_bytesTff7b72+Tff7b72+Tb4b4b4;
Te6edf3packet_queueTb4b4b4[Te6edf3queue_cursorTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3queue_cursor Tff7b72=Tff7b72= Te6edf3CONFIG_QUEUE_SIZETb4b4b4) Te6edf3queue_cursor Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FREQUENCYTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{
Tff7b72uint32_t Te6edf3freq Tff7b72= Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff24 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72<Tff7b72< T79c0ff16 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff3Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3freq Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_frequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lora_freq Tff7b72= Te6edf3freqTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setFrequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_frequencyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BANDWIDTHTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{
Tff7b72uint32_t Te6edf3bw Tff7b72= Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff24 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72<Tff7b72< T79c0ff16 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff2Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint32_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff3Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3bw Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_bandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lora_bw Tff7b72= Te6edf3bwTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setBandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_bandwidthTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_TXPOWERTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_txpowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3txp Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72#Tff7b72if MODEM == SX1262
Tff7b72#Tff7b72if HAS_LORA_PA
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> Te6edf3PA_MAX_OUTPUTTb4b4b4) Te6edf3txp Tff7b72= Te6edf3PA_MAX_OUTPUTTb4b4b4;
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff22Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff22Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72elif MODEM == SX1280
Tff7b72#Tff7b72if HAS_PA
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff20Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff20Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff13Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff13Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3txp Tff7b72> T79c0ff17Tb4b4b4) Te6edf3txp Tff7b72= T79c0ff17Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3lora_txp Tff7b72= Te6edf3txpTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setTXPowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_txpowerTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_SFTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_spreadingfactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3sf Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sf Tff7b72< T79c0ff5Tb4b4b4) Te6edf3sf Tff7b72= T79c0ff5Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sf Tff7b72> T79c0ff12Tb4b4b4) Te6edf3sf Tff7b72= T79c0ff12Tb4b4b4;
Te6edf3lora_sf Tff7b72= Te6edf3sfTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setSpreadingFactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_spreadingfactorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CRTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_codingrateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3cr Tff7b72= Te6edf3sbyteTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cr Tff7b72< T79c0ff5Tb4b4b4) Te6edf3cr Tff7b72= T79c0ff5Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cr Tff7b72> T79c0ff8Tb4b4b4) Te6edf3cr Tff7b72= T79c0ff8Tb4b4b4;
Te6edf3lora_cr Tff7b72= Te6edf3crTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3op_mode Tff7b72=Tff7b72= Te6edf3MODE_HOSTTb4b4b4) Te6edf3setCodingRateTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_codingrateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_IMPLICITTb4b4b4) Tb4b4b4{
Te6edf3set_implicit_lengthTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_implicit_lengthTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_LEAVETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_DISCONNECTEDTb4b4b4;
Te6edf3current_rssi Tff7b72= T79c0ff-292Tb4b4b4;
Te6edf3last_rssi Tff7b72= T79c0ff-292Tb4b4b4;
Te6edf3last_rssi_raw Tff7b72= T79c0ff0x00Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= T79c0ff0x80Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RADIO_STATETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_CONNECTEDTb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3stopRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3startRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_radiostateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_ST_ALOCKTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff2Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3at Tff7b72= Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3at Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3st_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3st_airtime_limit Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3atTff7b72/Tb4b4b4(T79c0ff100.0Tff7b72*T79c0ff100.0Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3st_airtime_limit Tff7b72>Tff7b72= T79c0ff1.0Tb4b4b4) Tb4b4b4{ Te6edf3st_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3kiss_indicate_st_alockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_LT_ALOCKTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff2Tb4b4b4) Tb4b4b4{
Tff7b72uint16_t Te6edf3at Tff7b72= Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72<Tff7b72< T79c0ff8 Tff7b72| Tb4b4b4(Tff7b72uint16_tTb4b4b4)Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3at Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3lt_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3lt_airtime_limit Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3atTff7b72/Tb4b4b4(T79c0ff100.0Tff7b72*T79c0ff100.0Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lt_airtime_limit Tff7b72>Tff7b72= T79c0ff1.0Tb4b4b4) Tb4b4b4{ Te6edf3lt_airtime_limit Tff7b72= T79c0ff0.0Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3kiss_indicate_lt_alockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_STAT_RXTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_stat_rxTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_STAT_TXTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_stat_txTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_STAT_RSSITb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RADIO_LOCKTb4b4b4) Tb4b4b4{
Te6edf3update_radio_lockTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_radio_lockTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BLINKTb4b4b4) Tb4b4b4{
Te6edf3led_indicate_infoTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RANDOMTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_randomTb4b4b4(Te6edf3getRandomTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DETECTTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3DETECT_REQTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Te6edf3cable_state Tff7b72= Te6edf3CABLE_STATE_CONNECTEDTb4b4b4;
Te6edf3kiss_indicate_detectTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_PROMISCTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3promisc_enableTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3promisc_disableTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3kiss_indicate_promiscTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_READYTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3queue_fullTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_readyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3kiss_indicate_not_readyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_UNLOCK_ROMTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3ROM_UNLOCK_BYTETb4b4b4) Tb4b4b4{
Te6edf3unlock_romTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_RESETTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3CMD_RESET_BYTETb4b4b4) Tb4b4b4{
Te6edf3hard_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_ROM_READTb4b4b4) Tb4b4b4{
Te6edf3kiss_dump_eepromTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CFG_READTb4b4b4) Tb4b4b4{
Te6edf3kiss_dump_configTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_ROM_WRITETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff2Tb4b4b4) Tb4b4b4{
Te6edf3eeprom_writeTb4b4b4(Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3cmdbufTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FW_VERSIONTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_versionTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_PLATFORMTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_platformTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_MCUTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_mcuTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BOARDTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_boardTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CONF_SAVETb4b4b4) Tb4b4b4{
Te6edf3eeprom_conf_saveTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_CONF_DELETETb4b4b4) Tb4b4b4{
Te6edf3eeprom_conf_deleteTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
Te6edf3boundary_clear_app_markerTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FB_EXTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY == true
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0xFFTb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_fbstateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3ext_fb_disableTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_fbstateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3ext_fb_enableTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_fbstateTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FB_WRITETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff9Tb4b4b4) Tb4b4b4{
Tff7b72uint8_t Td2a8ffline Tff7b72= Te6edf3cmdbufTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Td2a8ffline Tff7b72> T79c0ff63Tb4b4b4) Td2a8ffline Tff7b72= T79c0ff63Tb4b4b4;
Tff7b72int Te6edf3fb_o Tff7b72= Td2a8fflineTff7b72*T79c0ff8Tb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3fbTff7b72+Te6edf3fb_oTb4b4b4, Te6edf3cmdbufTff7b72+T79c0ff1Tb4b4b4, T79c0ff8Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FB_READTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72!Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3kiss_indicate_fbTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_READTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72!Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{ Te6edf3kiss_indicate_dispTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DEV_HASHTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72!Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_device_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DEV_SIGTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= Te6edf3DEV_SIG_LENTb4b4b4) Tb4b4b4{
Te6edf3memcpyTb4b4b4(Te6edf3dev_sigTb4b4b4, Te6edf3cmdbufTb4b4b4, Te6edf3DEV_SIG_LENTb4b4b4)Tb4b4b4;
Te6edf3device_save_signatureTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FW_UPDTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3firmware_update_mode Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3firmware_update_mode Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_HASHESTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_target_fw_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x02Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_fw_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x03Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_bootloader_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x04Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_partition_table_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_FW_HASHTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= Te6edf3DEV_HASH_LENTb4b4b4) Tb4b4b4{
Te6edf3memcpyTb4b4b4(Te6edf3dev_firmware_hash_targetTb4b4b4, Te6edf3cmdbufTb4b4b4, Te6edf3DEV_HASH_LENTb4b4b4)Tb4b4b4;
Te6edf3device_save_firmware_hashTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_CHNTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72> T79c0ff0 Tff7b72&Tff7b72& Te6edf3sbyte Tff7b72< T79c0ff14Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3eeprom_addrTb4b4b4(Te6edf3ADDR_CONF_WCHNTb4b4b4)Tb4b4b4, Te6edf3sbyteTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_MODETb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3WR_WIFI_OFF Tff7b72|Tff7b72| Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3WR_WIFI_STA Tff7b72|Tff7b72| Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3WR_WIFI_APTb4b4b4) Tb4b4b4{
Te6edf3wr_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3wifi_mode Tff7b72= Te6edf3sbyteTb4b4b4;
Te6edf3wifi_remote_initTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_SSIDTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff33Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3iTff7b72<Te6edf3frame_len Tff7b72&Tff7b72& Te6edf3iTff7b72<T79c0ff32Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_SSIDTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_SSIDTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, T79c0ff0x00Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_PSKTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff33Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3iTff7b72<Te6edf3frame_len Tff7b72&Tff7b72& Te6edf3iTff7b72<T79c0ff32Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_PSKTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_PSKTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, T79c0ff0x00Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_IPTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff4Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_IPTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_WIFI_NMTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{ Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72< Te6edf3CMD_LTb4b4b4) Te6edf3cmdbufTb4b4b4[Te6edf3frame_lenTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3sbyteTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3frame_len Tff7b72=Tff7b72= T79c0ff4Tb4b4b4) Tb4b4b4{ Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3iTff7b72<T79c0ff4Tb4b4b4; Te6edf3iTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3eeprom_updateTb4b4b4(Te6edf3config_addrTb4b4b4(Te6edf3ADDR_CONF_NMTff7b72+Te6edf3iTb4b4b4)Tb4b4b4, Te6edf3cmdbufTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BT_CTRLTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Tb4b4b4{
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{
Te6edf3bt_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x02Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_OFFTb4b4b4) Tb4b4b4{
Te6edf3bt_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3bt_enable_pairingTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_BT_UNPAIRTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= T79c0ff0x01Tb4b4b4) Tb4b4b4{ Te6edf3bt_debond_allTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_INTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3display_intensity Tff7b72= Te6edf3sbyteTb4b4b4;
Te6edf3di_conf_saveTb4b4b4(Te6edf3display_intensityTb4b4b4)Tb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_ADDRTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3display_addr Tff7b72= Te6edf3sbyteTb4b4b4;
Te6edf3da_conf_saveTb4b4b4(Te6edf3display_addrTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_BLNKTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3db_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_ROTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3drot_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DIS_IATb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3dia_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_DISP_RCNDTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72> T79c0ff0x00Tb4b4b4) Te6edf3recondition_display Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3command Tff7b72=Tff7b72= Te6edf3CMD_NP_INTTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_NP
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3FESCTb4b4b4) Tb4b4b4{
Te6edf3ESCAPE Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3ESCAPETb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFENDTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FENDTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3sbyte Tff7b72=Tff7b72= Te6edf3TFESCTb4b4b4) Te6edf3sbyte Tff7b72= Te6edf3FESCTb4b4b4;
Te6edf3ESCAPE Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Te6edf3sbyteTb4b4b4;
Te6edf3led_set_intensityTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Te6edf3np_int_conf_saveTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3portMUX_TYPE Te6edf3update_lock Tff7b72= Te6edf3portMUX_INITIALIZER_UNLOCKEDTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72bool Te6edf3medium_freeTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3update_modem_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3avoid_interference Tff7b72&Tff7b72& Te6edf3interference_detectedTb4b4b4) Tb4b4b4{ Tff7b72return Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72return Tff7b72!Te6edf3dcdTb4b4b4;
Tb4b4b4}
Tff7b72bool Te6edf3noise_floor_sampled Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72int Te6edf3noise_floor_sample Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72int Te6edf3noise_floor_bufferTb4b4b4[Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4] Tff7b72= Tb4b4b4{T79c0ff0Tb4b4b4}Tb4b4b4;
Tff7b72void Te6edf3update_noise_floorTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3dcdTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if BOARD_MODEL != BOARD_HELTEC32_V4
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3noise_floor_sampled Tff7b72|Tff7b72| Te6edf3current_rssi Tff7b72< Te6edf3noise_floor Tff7b72+ Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tb4b4b4(Tff7b72!Te6edf3noise_floor_sampled Tff7b72|Tff7b72| Te6edf3current_rssi Tff7b72< Te6edf3noise_floor Tff7b72+ Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3noise_floor_sampled Tff7b72&Tff7b72& Tb4b4b4(Te6edf3noise_floor Tff7b72< Te6edf3LNA_GD_THRSHLD Tff7b72&Tff7b72& Te6edf3current_rssi Tff7b72<Tff7b72= Te6edf3LNA_GD_LIMITTb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_LORA_LNA
T8b949e// Discard invalid samples due to gain variance
T8b949e// during LoRa LNA re-calibration
Tff7b72if Tb4b4b4(Te6edf3current_rssi Tff7b72< Te6edf3noise_floorTff7b72-Te6edf3LORA_LNA_GVTTb4b4b4) Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72bool Te6edf3sum_noise_floor Tff7b72= Tff7b72falseTb4b4b4;
Te6edf3noise_floor_bufferTb4b4b4[Te6edf3noise_floor_sampleTb4b4b4] Tff7b72= Te6edf3current_rssiTb4b4b4;
Te6edf3noise_floor_sample Tff7b72= Te6edf3noise_floor_sampleTff7b72+T79c0ff1Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3noise_floor_sample Tff7b72>Tff7b72= Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4) Tb4b4b4{
Te6edf3noise_floor_sample Tff7b72%Tff7b72= Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4;
Te6edf3noise_floor_sampled Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3sum_noise_floor Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3noise_floor_sampled Tff7b72&Tff7b72& Te6edf3sum_noise_floorTb4b4b4) Tb4b4b4{
Te6edf3noise_floor Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72int Te6edf3ni Tff7b72= T79c0ff0Tb4b4b4; Te6edf3ni Tff7b72< Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4; Te6edf3niTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{ Te6edf3noise_floor Tff7b72+Tff7b72= Te6edf3noise_floor_bufferTb4b4b4[Te6edf3niTb4b4b4]Tb4b4b4; Tb4b4b4}
Te6edf3noise_floor Tff7b72/Tff7b72= Te6edf3NOISE_FLOOR_SAMPLESTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72define LED_ID_TRIG 16
Tff7b72uint8_t Te6edf3led_id_filter Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72uint32_t Te6edf3interference_start Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72bool Te6edf3interference_persists Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72void Te6edf3update_modem_statusTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3portENTER_CRITICALTb4b4b4(Tff7b72&Te6edf3update_lockTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3portENTER_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72bool Te6edf3carrier_detected Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3dcdTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3current_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3currentRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_status_update Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3portEXIT_CRITICALTb4b4b4(Tff7b72&Te6edf3update_lockTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3portEXIT_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC32_V4
Tff7b72if Tb4b4b4(Te6edf3noise_floor Tff7b72> Te6edf3LNA_GD_THRSHLDTb4b4b4) Tb4b4b4{ Te6edf3interference_detected Tff7b72= Tff7b72!Te6edf3carrier_detected Tff7b72&Tff7b72& Tb4b4b4(Te6edf3current_rssi Tff7b72> Tb4b4b4(Te6edf3noise_floorTff7b72+Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3interference_detected Tff7b72= Tff7b72!Te6edf3carrier_detected Tff7b72&Tff7b72& Tb4b4b4(Te6edf3current_rssi Tff7b72> Te6edf3LNA_GD_LIMITTb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3interference_detected Tff7b72= Tff7b72!Te6edf3carrier_detected Tff7b72&Tff7b72& Tb4b4b4(Te6edf3current_rssi Tff7b72> Tb4b4b4(Te6edf3noise_floorTff7b72+Te6edf3CSMA_INFR_THRESHOLD_DBTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3interference_detectedTb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3led_id_filter Tff7b72< Te6edf3LED_ID_TRIGTb4b4b4) Tb4b4b4{ Te6edf3led_id_filter Tff7b72+Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72if Tb4b4b4(Te6edf3led_id_filter Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{Te6edf3led_id_filter Tff7b72-Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4} Tb4b4b4}
T8b949e// Handle potential false interference detection due to
T8b949e// LNA recalibration, antenna swap, moving into new RF
T8b949e// environment or similar.
Tff7b72if Tb4b4b4(Te6edf3interference_detected Tff7b72&Tff7b72& Te6edf3current_rssi Tff7b72< Te6edf3CSMA_RFENV_RECAL_LIMIT_DBTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3interference_persistsTb4b4b4) Tb4b4b4{ Te6edf3interference_persists Tff7b72= Tff7b72trueTb4b4b4; Te6edf3interference_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4)Tff7b72-Te6edf3interference_start Tff7b72>Tff7b72= Te6edf3CSMA_RFENV_RECAL_MSTb4b4b4) Tb4b4b4{ Te6edf3noise_floor_sampled Tff7b72= Tff7b72falseTb4b4b4; Te6edf3interference_persists Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3interference_persists Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3carrier_detectedTb4b4b4) Tb4b4b4{ Te6edf3dcd Tff7b72= Tff7b72trueTb4b4b4; Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3dcd Tff7b72= Tff7b72falseTb4b4b4; Tb4b4b4}
Te6edf3dcd_led Tff7b72= Te6edf3dcdTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dcd_ledTb4b4b4) Tb4b4b4{ Te6edf3led_rx_onTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3interference_detectedTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3led_id_filter Tff7b72>Tff7b72= Te6edf3LED_ID_TRIG Tff7b72&Tff7b72& Te6edf3noise_floor_sampledTb4b4b4) Tb4b4b4{ Te6edf3led_id_onTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3airtime_lockTb4b4b4) Tb4b4b4{ Te6edf3led_indicate_airtime_lockTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{ Te6edf3led_rx_offTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3led_id_offTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72void Te6edf3check_modem_statusTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4)Tff7b72-Te6edf3last_status_update Tff7b72>Tff7b72= Te6edf3status_interval_msTb4b4b4) Tb4b4b4{
Te6edf3update_modem_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3update_noise_floorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3dcdTb4b4b4) Tb4b4b4{
Te6edf3util_samplesTb4b4b4[Te6edf3dcd_sample Tff7b72>Tff7b72> T79c0ff3Tb4b4b4] Tff7b72|Tff7b72= Tb4b4b4(T79c0ff1 Tff7b72<Tff7b72< Tb4b4b4(Te6edf3dcd_sample Tff7b72& T79c0ff7Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3util_samplesTb4b4b4[Te6edf3dcd_sample Tff7b72>Tff7b72> T79c0ff3Tb4b4b4] Tff7b72&Tff7b72= Tff7b72~Tb4b4b4(T79c0ff1 Tff7b72<Tff7b72< Tb4b4b4(Te6edf3dcd_sample Tff7b72& T79c0ff7Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3dcd_sample Tff7b72= Tb4b4b4(Te6edf3dcd_sampleTff7b72+T79c0ff1Tb4b4b4)Tff7b72%Te6edf3DCD_SAMPLESTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dcd_sample Tff7b72% Te6edf3UTIL_UPDATE_INTERVAL Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72int Te6edf3util_count Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72int Te6edf3ui Tff7b72= T79c0ff0Tb4b4b4; Te6edf3ui Tff7b72< Te6edf3DCD_BITFIELD_SIZETb4b4b4; Te6edf3uiTff7b72+Tff7b72+Tb4b4b4) Tb4b4b4{
Tff7b72uint8_t Te6edf3b Tff7b72= Te6edf3util_samplesTb4b4b4[Te6edf3uiTb4b4b4]Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3bTb4b4b4) Tb4b4b4{ Te6edf3util_count Tff7b72+Tff7b72= Tb4b4b4(Te6edf3b Tff7b72& T79c0ff1Tb4b4b4)Tb4b4b4; Te6edf3b Tff7b72>Tff7b72>Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Te6edf3local_channel_util Tff7b72= Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3util_count Tff7b72/ Tb4b4b4(Tff7b72floatTb4b4b4)Te6edf3DCD_SAMPLESTb4b4b4;
Te6edf3total_channel_util Tff7b72= Te6edf3local_channel_util Tff7b72+ Te6edf3airtimeTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3total_channel_util Tff7b72> T79c0ff1.0Tb4b4b4) Te6edf3total_channel_util Tff7b72= T79c0ff1.0Tb4b4b4;
Tff7b72int16_t Te6edf3cb Tff7b72= Te6edf3current_airtime_binTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72uint16_t Te6edf3nb Tff7b72= Te6edf3cbTff7b72+T79c0ff1Tb4b4b4; Tff7b72if Tb4b4b4(Te6edf3nb Tff7b72=Tff7b72= Te6edf3AIRTIME_BINSTb4b4b4) Tb4b4b4{ Te6edf3nb Tff7b72= T79c0ff0Tb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3total_channel_util Tff7b72> Te6edf3longterm_binsTb4b4b4[Te6edf3cbTb4b4b4]Tb4b4b4) Te6edf3longterm_binsTb4b4b4[Te6edf3cbTb4b4b4] Tff7b72= Te6edf3total_channel_utilTb4b4b4;
Te6edf3longterm_binsTb4b4b4[Te6edf3nbTb4b4b4] Tff7b72= T79c0ff0.0Tb4b4b4;
Te6edf3update_airtimeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tff7b72void Te6edf3validate_statusTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_1284P
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= Te6edf3OPTIBOOT_MCUSRTb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= Te6edf3PORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= Te6edf3BORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= Te6edf3WDRFTb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_2560
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= Te6edf3OPTIBOOT_MCUSRTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72=Tff7b72= T79c0ff0x00Tb4b4b4) Te6edf3boot_flags Tff7b72= T79c0ff0x03Tb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= Te6edf3PORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= Te6edf3BORFTb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= Te6edf3WDRFTb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_ESP32
T8b949e// TODO: Get ESP32 boot flags
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= T79c0ff0x02Tb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= T79c0ff0x01Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
T8b949e// TODO: Get NRF52 boot flags
Tff7b72uint8_t Te6edf3boot_flags Tff7b72= T79c0ff0x02Tb4b4b4;
Tff7b72uint8_t Te6edf3F_POR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_BOR Tff7b72= T79c0ff0x00Tb4b4b4;
Tff7b72uint8_t Te6edf3F_WDR Tff7b72= T79c0ff0x01Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3hw_ready Tff7b72|Tff7b72| Te6edf3device_init_doneTb4b4b4) Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffError, invalid hardware check stateTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3led_indicate_boot_errorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72& Tb4b4b4(T79c0ff1Tff7b72<Tff7b72<Te6edf3F_PORTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3boot_vector Tff7b72= Te6edf3START_FROM_POWERONTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72& Tb4b4b4(T79c0ff1Tff7b72<Tff7b72<Te6edf3F_BORTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3boot_vector Tff7b72= Te6edf3START_FROM_BROWNOUTTb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3boot_flags Tff7b72& Tb4b4b4(T79c0ff1Tff7b72<Tff7b72<Te6edf3F_WDRTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3boot_vector Tff7b72= Te6edf3START_FROM_BOOTLOADERTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffError, indeterminate boot vectorTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3led_indicate_boot_errorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3boot_vector Tff7b72=Tff7b72= Te6edf3START_FROM_BOOTLOADER Tff7b72|Tff7b72| Te6edf3boot_vector Tff7b72=Tff7b72= Te6edf3START_FROM_POWERONTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Boundary Mode: bypass EEPROM provisioning checks.
T8b949e// We don't need rnodeconf provisioning — LoRa config comes from
T8b949e// the web portal / EEPROM config area instead.
Tff7b72if Tb4b4b4(Te6edf3modem_installedTb4b4b4) Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3eeprom_ok Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Provisioning check bypassed, modem installedTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
T8b949e// Load LoRa config from EEPROM (written by config portal)
Tff7b72if Tb4b4b4(Te6edf3eeprom_have_confTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3eeprom_conf_loadTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Loaded LoRa config from EEPROMTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Use sensible defaults if no config saved yet
Te6edf3lora_freq Tff7b72= T79c0ff914875000Tb4b4b4;
Te6edf3lora_bw Tff7b72= T79c0ff125000Tb4b4b4;
Te6edf3lora_sf Tff7b72= T79c0ff10Tb4b4b4;
Te6edf3lora_cr Tff7b72= T79c0ff5Tb4b4b4;
Te6edf3lora_txp Tff7b72= T79c0ff28Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] No LoRa config in EEPROM, using defaultsTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3op_mode Tff7b72= Te6edf3MODE_TNCTb4b4b4;
Te6edf3startRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] No radio module foundTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Te6edf3eeprom_lock_setTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3eeprom_product_validTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3eeprom_model_validTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3eeprom_hwrev_validTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3eeprom_checksum_validTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3eeprom_ok Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3modem_installedTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32 || PLATFORM == PLATFORM_NRF52
Tff7b72if Tb4b4b4(Te6edf3device_initTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3hw_ready Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffNo radio module foundTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3hw_ready Tff7b72&Tff7b72& Te6edf3eeprom_have_confTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3eeprom_conf_loadTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3op_mode Tff7b72= Te6edf3MODE_TNCTb4b4b4;
Te6edf3startRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffInvalid EEPROM checksumTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffInvalid EEPROM configurationTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffDevice unprovisioned, no device configuration found in EEPROMTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// BOUNDARY_MODE
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3hw_ready Tff7b72= Tff7b72falseTb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffError, incorrect boot vectorTffea00\rTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_readyTb4b4b4) Tb4b4b4{
Te6edf3device_init_done Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3led_indicate_boot_errorTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72void Te6edf3update_csma_parametersTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72int Te6edf3airtime_pct Tff7b72= Tb4b4b4(Tff7b72intTb4b4b4)Tb4b4b4(Te6edf3airtimeTff7b72*T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72int Te6edf3new_cw_band Tff7b72= Te6edf3cw_bandTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3airtime_pct Tff7b72<Tff7b72= Te6edf3CSMA_BAND_1_MAX_AIRTIMETb4b4b4) Tb4b4b4{ Te6edf3new_cw_band Tff7b72= T79c0ff1Tb4b4b4; Tb4b4b4}
Tff7b72else Tb4b4b4{
Tff7b72int Te6edf3at Tff7b72= Te6edf3airtime_pct Tff7b72+ Te6edf3CSMA_BAND_1_MAX_AIRTIMETb4b4b4;
Te6edf3new_cw_band Tff7b72= Td2a8ffmapTb4b4b4(Te6edf3atTb4b4b4, Te6edf3CSMA_BAND_1_MAX_AIRTIMETb4b4b4, Te6edf3CSMA_BAND_N_MIN_AIRTIMETb4b4b4, T79c0ff2Tb4b4b4, Te6edf3CSMA_CW_BANDSTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3new_cw_band Tff7b72> Te6edf3CSMA_CW_BANDSTb4b4b4) Tb4b4b4{ Te6edf3new_cw_band Tff7b72= Te6edf3CSMA_CW_BANDSTb4b4b4; Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3new_cw_band Tff7b72!Tff7b72= Te6edf3cw_bandTb4b4b4) Tb4b4b4{
Te6edf3cw_band Tff7b72= Tb4b4b4(Tff7b72uint8_tTb4b4b4)Tb4b4b4(Te6edf3new_cw_bandTb4b4b4)Tb4b4b4;
Te6edf3cw_min Tff7b72= Tb4b4b4(Te6edf3cw_bandT79c0ff-1Tb4b4b4) Tff7b72* Te6edf3CSMA_CW_PER_BAND_WINDOWSTb4b4b4;
Te6edf3cw_max Tff7b72= Tb4b4b4(Te6edf3cw_bandTb4b4b4) Tff7b72* Te6edf3CSMA_CW_PER_BAND_WINDOWS Tff7b72- T79c0ff1Tb4b4b4;
Te6edf3kiss_indicate_csma_statsTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72void Te6edf3tx_queue_handlerTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3airtime_lock Tff7b72&Tff7b72& Te6edf3queue_height Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3csma_cw Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{
Te6edf3csma_cw Tff7b72= Td2a8ffrandomTb4b4b4(Te6edf3cw_minTb4b4b4, Te6edf3cw_maxTb4b4b4)Tb4b4b4;
Te6edf3cw_wait_target Tff7b72= Te6edf3csma_cw Tff7b72* Te6edf3csma_slot_msTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3difs_wait_start Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{ T8b949e// DIFS wait not yet started
Tff7b72if Tb4b4b4(Te6edf3medium_freeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3difs_wait_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// Set DIFS wait start time
Tff7b72else Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4} Tb4b4b4} T8b949e// Medium not yet free, continue waiting
Tff7b72else Tb4b4b4{ T8b949e// We are waiting for DIFS or CW to pass
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3medium_freeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3difs_wait_start Tff7b72= T79c0ff-1Tb4b4b4; Te6edf3cw_wait_start Tff7b72= T79c0ff-1Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// Medium became occupied while in DIFS wait, restart waiting when free again
Tff7b72else Tb4b4b4{ T8b949e// Medium is free, so continue waiting
Tff7b72if Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3difs_wait_startTff7b72+Te6edf3difs_msTb4b4b4) Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// DIFS has not yet passed, continue waiting
Tff7b72else Tb4b4b4{ T8b949e// DIFS has passed, and we are now in CW wait
Tff7b72if Tb4b4b4(Te6edf3cw_wait_start Tff7b72=Tff7b72= T79c0ff-1Tb4b4b4) Tb4b4b4{ Te6edf3cw_wait_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4; Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// If we haven't started counting CW wait time, do it from now
Tff7b72else Tb4b4b4{ T8b949e// If we are already counting CW wait time, add it to the counter
Te6edf3cw_wait_passed Tff7b72+Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tff7b72-Te6edf3cw_wait_startTb4b4b4; Te6edf3cw_wait_start Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3cw_wait_passed Tff7b72< Te6edf3cw_wait_targetTb4b4b4) Tb4b4b4{ Tff7b72returnTb4b4b4; Tb4b4b4} T8b949e// Contention window wait time has not yet passed, continue waiting
Tff7b72else Tb4b4b4{ T8b949e// Wait time has passed, flush the queue
Tff7b72bool Te6edf3should_flush Tff7b72= Tff7b72!Te6edf3lora_limit_rate Tff7b72&Tff7b72& Tff7b72!Te6edf3lora_guard_rateTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3should_flushTb4b4b4) Tb4b4b4{ Te6edf3flush_queueTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4} Tff7b72else Tb4b4b4{ Te6edf3pop_queueTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3cw_wait_passed Tff7b72= T79c0ff0Tb4b4b4; Te6edf3csma_cw Tff7b72= T79c0ff-1Tb4b4b4; Te6edf3difs_wait_start Tff7b72= T79c0ff-1Tb4b4b4; Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72void Te6edf3work_while_waitingTb4b4b4(Tb4b4b4) Tb4b4b4{ Tffa657loopTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72void Tffa657loopTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef HAS_RNS
T8b949e// CBA
Tff7b72if Tb4b4b4(Te6edf3reticulumTb4b4b4) Tb4b4b4{
Te6edf3reticulumTb4b4b4.Tffa657loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Periodic interface-discovery announcer (Reticulum manual §Interfaces).
T8b949e// No-op until Reticulum is up and the user has enabled "Advertise Device".
Tff7b72if Tb4b4b4(Te6edf3reticulumTb4b4b4) Tb4b4b4{
Te6edf3advertise_loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// ── Clear bootloop counter once we reach a stable loop iteration ──────────
Tff7b72if Tb4b4b4(Te6edf3bootloop_magic Tff7b72=Tff7b72= Te6edf3BOOTLOOP_MAGICTb4b4b4) Tb4b4b4{
Te6edf3bootloop_magic Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3bootloop_count Tff7b72= T79c0ff0Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Boot stable — bootloop counter clearedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// ── Heap + WiFi watchdog ───────────────────────────────────────────────────
T8b949e// Monitor heap and WiFi health. Auto-reboot on critical conditions:
T8b949e// 1) Internal heap drops below 20KB (WiFi needs ~16KB for RX buffers)
T8b949e// 2) WiFi down for >15s after having been connected (unrecoverable)
Tb4b4b4{
Tff7b72static Tff7b72bool Te6edf3_wifi_watchdog_armed Tff7b72= Tff7b72falseTb4b4b4; T8b949e// armed once WiFi first connects
Tff7b72static Tff7b72uint32_t Te6edf3_wifi_lost_at Tff7b72= T79c0ff0Tb4b4b4; T8b949e// millis() when WiFi first lost
Tff7b72static Tff7b72const Tff7b72uint32_t Te6edf3WIFI_GRACE_MS Tff7b72= T79c0ff15000Tb4b4b4; T8b949e// 15s grace before reboot
Tff7b72static Tff7b72const Tff7b72uint32_t Te6edf3HEAP_CRITICAL Tff7b72= T79c0ff20000Tb4b4b4; T8b949e// 20KB minimum internal heap
T8b949e// ── Heap pressure check (runs always) ─────────────────────────────────
Tff7b72uint32_t Te6edf3free_heap Tff7b72= Te6edf3ESPTb4b4b4.Te6edf3getFreeHeapTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3free_heap Tff7b72< Te6edf3HEAP_CRITICALTb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Tffea00\rTffea00\nTa5d6ff[WATCHDOG] CRITICAL: Free heap %u < %u — REBOOTINGTffea00\rTffea00\nTa5d6ff"Tb4b4b4,
Te6edf3free_heapTb4b4b4, Te6edf3HEAP_CRITICALTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[WATCHDOG] Min free: %u Max alloc: %uTffea00\rTffea00\nTa5d6ff"Tb4b4b4,
Te6edf3ESPTb4b4b4.Te6edf3getMinFreeHeapTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3ESPTb4b4b4.Te6edf3getMaxAllocHeapTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Te6edf3ESPTb4b4b4.Te6edf3restartTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72bool Te6edf3wifi_now Tff7b72= Te6edf3wifi_is_connectedTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// Arm the watchdog once WiFi has been up at least once
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3_wifi_watchdog_armed Tff7b72&Tff7b72& Te6edf3wifi_nowTb4b4b4) Tb4b4b4{
Te6edf3_wifi_watchdog_armed Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3_wifi_lost_at Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3_wifi_watchdog_armed Tff7b72&Tff7b72& Tff7b72!Te6edf3wifi_nowTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3_wifi_lost_at Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3_wifi_lost_at Tff7b72= Td2a8ffmillisTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Tffea00\rTffea00\nTa5d6ff[WATCHDOG] WiFi lost at %lu ms (grace %lu ms)Tffea00\rTffea00\nTa5d6ff"Tb4b4b4,
Te6edf3_wifi_lost_atTb4b4b4, Te6edf3WIFI_GRACE_MSTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[WATCHDOG] WiFi.status()=%d heap=%u min_heap=%uTffea00\rTffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4(Tff7b72intTb4b4b4)Td2a8ffWiFiTb4b4b4.Te6edf3statusTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3free_heapTb4b4b4, Te6edf3ESPTb4b4b4.Te6edf3getMinFreeHeapTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// Check if grace period expired — unrecoverable, reboot
Tff7b72if Tb4b4b4(Tb4b4b4(Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3_wifi_lost_atTb4b4b4) Tff7b72>Tff7b72= Te6edf3WIFI_GRACE_MSTb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Tffea00\rTffea00\nTa5d6ff[WATCHDOG] WiFi down %lu ms — REBOOTINGTffea00\rTffea00\nTa5d6ff"Tb4b4b4,
Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3_wifi_lost_atTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[WATCHDOG] WiFi.status()=%d heap=%uTffea00\rTffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4(Tff7b72intTb4b4b4)Td2a8ffWiFiTb4b4b4.Te6edf3statusTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3ESPTb4b4b4.Te6edf3getFreeHeapTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[WATCHDOG] Bridged: L→T=%lu T→L=%luTffea00\rTffea00\nTa5d6ff"Tb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3packets_bridged_lora_to_tcpTb4b4b4,
Te6edf3boundary_stateTb4b4b4.Te6edf3packets_bridged_tcp_to_loraTb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffflushTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Te6edf3ESPTb4b4b4.Te6edf3restartTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3_wifi_watchdog_armed Tff7b72&Tff7b72& Te6edf3wifi_now Tff7b72&Tff7b72& Te6edf3_wifi_lost_at Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
T8b949e// WiFi recovered within grace period
Td2a8ffSerialTb4b4b4.Te6edf3printfTb4b4b4(Ta5d6ff"Ta5d6ff[WATCHDOG] WiFi back after %lu msTffea00\rTffea00\nTa5d6ff"Tb4b4b4, Td2a8ffmillisTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3_wifi_lost_atTb4b4b4)Tb4b4b4;
Te6edf3_wifi_lost_at Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Boundary Mode: poll TCP interfaces for incoming data
Tff7b72if Tb4b4b4(Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_enabledTb4b4b4) Tb4b4b4{
T8b949e// Start TCP interfaces if WiFi just connected and not yet started
Tff7b72if Tb4b4b4(Te6edf3wifi_is_connectedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3tcp_interface_ptr Tff7b72&Tff7b72& Tff7b72!Te6edf3tcp_interface_ptrTff7b72-Tff7b72>Te6edf3isStartedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3tcp_interface_ptrTff7b72-Tff7b72>Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] WiFi connected, TCP backbone startedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3local_tcp_interface_ptr Tff7b72&Tff7b72& Tff7b72!Te6edf3local_tcp_interface_ptrTff7b72-Tff7b72>Te6edf3isStartedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3local_tcp_interface_ptrTff7b72-Tff7b72>Te6edf3startTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] WiFi connected, local TCP server startedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3tcp_interface_ptrTb4b4b4) Tb4b4b4{
Te6edf3tcp_interface_ptrTff7b72-Tff7b72>Tffa657loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3local_tcp_interface_ptrTb4b4b4) Tb4b4b4{
Te6edf3local_tcp_interface_ptrTff7b72-Tff7b72>Tffa657loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3boundary_stateTb4b4b4.Te6edf3tcp_connected Tff7b72= Tb4b4b4(Te6edf3tcp_interface_ptr Tff7b72&Tff7b72& Te6edf3tcp_interface_ptrTff7b72-Tff7b72>Te6edf3isConnectedTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3boundary_stateTb4b4b4.Te6edf3ap_tcp_connected Tff7b72= Tb4b4b4(Te6edf3local_tcp_interface_ptr Tff7b72&Tff7b72& Te6edf3local_tcp_interface_ptrTff7b72-Tff7b72>Te6edf3isConnectedTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3boundary_stateTb4b4b4.Te6edf3wifi_connected Tff7b72= Te6edf3wifi_is_connectedTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3radio_onlineTb4b4b4) Tb4b4b4{
T8b949e// Poll for deferred DIO0 interrupt (SPI work moved out of ISR)
Te6edf3LoRaTff7b72-Tff7b72>Te6edf3pollDio0Tb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3modem_packet_t Tff7b72*Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;
Tff7b72ifTb4b4b4(Te6edf3modem_packet_queue Tff7b72&Tff7b72& Te6edf3xQueueReceiveTb4b4b4(Te6edf3modem_packet_queueTb4b4b4, Tff7b72&Te6edf3modem_packetTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= Te6edf3pdTRUE Tff7b72&Tff7b72& Te6edf3modem_packetTb4b4b4) Tb4b4b4{
Te6edf3host_write_len Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4;
Te6edf3last_rssi Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3rssiTb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3snr_rawTb4b4b4;
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3pbufTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3dataTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3freeTb4b4b4(Te6edf3modem_packetTb4b4b4)Tb4b4b4;
Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3airtime_lock Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3st_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3airtime Tff7b72>Tff7b72= Te6edf3st_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lt_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3longterm_airtime Tff7b72>Tff7b72= Te6edf3lt_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3modem_packet_t Tff7b72*Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;
Tff7b72ifTb4b4b4(Te6edf3modem_packet_queue Tff7b72&Tff7b72& Te6edf3xQueueReceiveTb4b4b4(Te6edf3modem_packet_queueTb4b4b4, Tff7b72&Te6edf3modem_packetTb4b4b4, T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= Te6edf3pdTRUE Tff7b72&Tff7b72& Te6edf3modem_packetTb4b4b4) Tb4b4b4{
Te6edf3memcpyTb4b4b4(Tff7b72&Te6edf3pbufTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3dataTb4b4b4, Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3host_write_len Tff7b72= Te6edf3modem_packetTff7b72-Tff7b72>Te6edf3lenTb4b4b4;
Te6edf3freeTb4b4b4(Te6edf3modem_packetTb4b4b4)Tb4b4b4;
Te6edf3modem_packet Tff7b72= Tffa657NULLTb4b4b4;
Te6edf3portENTER_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_rssi Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetRssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3last_snr_raw Tff7b72= Te6edf3LoRaTff7b72-Tff7b72>Te6edf3packetSnrRawTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3portEXIT_CRITICALTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_rssiTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_indicate_stat_snrTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3kiss_write_packetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3airtime_lock Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3st_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3airtime Tff7b72>Tff7b72= Te6edf3st_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3lt_airtime_limit Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72&Tff7b72& Te6edf3longterm_airtime Tff7b72>Tff7b72= Te6edf3lt_airtime_limitTb4b4b4) Te6edf3airtime_lock Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3tx_queue_handlerTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3check_modem_statusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3hw_readyTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3console_activeTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_CONSOLE
Te6edf3console_loopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3led_indicate_standbyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3led_indicate_not_readyTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stopRadioTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Te6edf3buffer_serialTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isemptyTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Te6edf3serial_pollTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isempty_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Te6edf3serial_pollTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_DISPLAY
Tff7b72if Tb4b4b4(Te6edf3disp_ready Tff7b72&Tff7b72& Tff7b72!Te6edf3display_updatingTb4b4b4) Te6edf3update_displayTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// LED solid when operational on V3/V4 boards (yield to fast blink during white screen)
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC32_V3
Tff7b72if Tb4b4b4(Te6edf3radio_online Tff7b72&Tff7b72& Tff7b72!Te6edf3display_lock_whiteTb4b4b4) Tb4b4b4{
Te6edf3headless_led_solidTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_PMU
Tff7b72if Tb4b4b4(Te6edf3pmu_readyTb4b4b4) Te6edf3update_pmuTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3console_active Tff7b72&Tff7b72& Te6edf3bt_readyTb4b4b4) Te6edf3update_btTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3wifi_initializedTb4b4b4) Te6edf3update_wifiTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_INPUT
Te6edf3input_readTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
T8b949e// Feed WDT
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32
Te6edf3esp_task_wdt_resetTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_NRF52
Te6edf3NRF_WDTTff7b72-Tff7b72>Te6edf3RRTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72= Te6edf3WDT_RR_RR_ReloadTb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72if Tb4b4b4(Te6edf3memory_lowTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32
Tff7b72if Tb4b4b4(Te6edf3esp_get_free_heap_sizeTb4b4b4(Tb4b4b4) Tff7b72< T79c0ff8192Tb4b4b4) Tb4b4b4{
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MEMORY_LOWTb4b4b4)Tb4b4b4; Te6edf3memory_low Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3memory_low Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
Te6edf3kiss_indicate_errorTb4b4b4(Te6edf3ERROR_MEMORY_LOWTb4b4b4)Tb4b4b4; Te6edf3memory_low Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}
Tb4b4b4}
Tff7b72void Te6edf3sleep_nowTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_SLEEP == true
Te6edf3stopRadioTb4b4b4(Tb4b4b4)Tb4b4b4; T8b949e// TODO: Check this on all platforms
Tff7b72#Tff7b72if PLATFORM == PLATFORM_ESP32
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_XIAO_S3
Tff7b72#Tff7b72if HAS_DISPLAY
Te6edf3display_intensity Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3update_displayTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC32_V4
Te6edf3headless_led_offTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3headless_led_detach_pwmTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_CPSTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_CSDTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3LORA_PA_PWR_ENTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3VextTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if PIN_DISP_SLEEP >= 0
Td2a8ffpinModeTb4b4b4(Te6edf3PIN_DISP_SLEEPTb4b4b4, Tff7b72OUTPUTTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_DISP_SLEEPTb4b4b4, Te6edf3DISP_SLEEP_LEVELTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72if HAS_BLUETOOTH
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
Te6edf3esp_sleep_enable_ext0_wakeupTb4b4b4(Te6edf3PIN_WAKEUPTb4b4b4, Te6edf3WAKEUP_LEVELTb4b4b4)Tb4b4b4;
Te6edf3esp_deep_sleep_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif PLATFORM == PLATFORM_NRF52
Tff7b72#Tff7b72if BOARD_MODEL == BOARD_HELTEC_T114
Te6edf3npsetTb4b4b4(T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4,T79c0ff0Tb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, Tff7b72LOWTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_T114_TFT_BLGTTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Td2a8ffdigitalWriteTb4b4b4(Te6edf3PIN_T114_TFT_ENTb4b4b4, Tff7b72HIGHTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif BOARD_MODEL == BOARD_TECHO
Tff7b72for Tb4b4b4(Tff7b72uint8_t Te6edf3i Tff7b72= Te6edf3display_intensityTb4b4b4; Te6edf3i Tff7b72> T79c0ff0Tb4b4b4; Te6edf3iTff7b72-Tff7b72-Tb4b4b4) Tb4b4b4{ Td2a8ffanalogWriteTb4b4b4(Te6edf3pin_backlightTb4b4b4, Te6edf3iT79c0ff-1Tb4b4b4)Tb4b4b4; Td2a8ffdelayTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3epd_blackTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4; Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4; Te6edf3epd_blackTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4; Td2a8ffdelayTb4b4b4(T79c0ff300Tb4b4b4)Tb4b4b4; Te6edf3epd_blackTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff2000Tb4b4b4)Tb4b4b4;
Td2a8ffanalogWriteTb4b4b4(Te6edf3PIN_VEXT_ENTb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3sd_power_gpregret_setTb4b4b4(T79c0ff0Tb4b4b4, T79c0ff0x6dTb4b4b4)Tb4b4b4;
Te6edf3nrf_gpio_cfg_sense_inputTb4b4b4(Te6edf3pin_btn_usr1Tb4b4b4, Te6edf3NRF_GPIO_PIN_PULLUPTb4b4b4, Te6edf3NRF_GPIO_PIN_SENSE_LOWTb4b4b4)Tb4b4b4;
Te6edf3NRF_POWERTff7b72-Tff7b72>Te6edf3SYSTEMOFF Tff7b72= T79c0ff1Tb4b4b4;
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72void Te6edf3button_eventTb4b4b4(Tff7b72uint8_t Te6edf3eventTb4b4b4, Tff7b72unsigned Tff7b72long Te6edf3durationTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
Tff7b72if Tb4b4b4(Te6edf3display_blankedTb4b4b4) Tb4b4b4{
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72ifdef BOUNDARY_MODE
T8b949e// Boundary Mode button mapping:
T8b949e// >5s = reboot into config mode (clean restart)
T8b949e// >700ms = sleep
T8b949e// short = display unblank
Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff5000Tb4b4b4) Tb4b4b4{
Td2a8ffSerialTb4b4b4.Td2a8ffprintlnTb4b4b4(Ta5d6ff"Ta5d6ff[Boundary] Button hold >5s — rebooting into config modeTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3boundary_config_request Tff7b72= Te6edf3BOUNDARY_CONFIG_MAGICTb4b4b4;
Td2a8ffdelayTb4b4b4(T79c0ff100Tb4b4b4)Tb4b4b4;
Te6edf3ESPTb4b4b4.Te6edf3restartTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff700Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_SLEEP
Te6edf3sleep_nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3display_unblankTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72else
T8b949e// Standard RNode button mapping
Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff10000Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_CONSOLE
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Te6edf3console_active Tff7b72= Tff7b72trueTb4b4b4;
Te6edf3console_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff5000Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{ Te6edf3bt_enable_pairingTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3duration Tff7b72> T79c0ff700Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if HAS_SLEEP
Te6edf3sleep_nowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_OFFTb4b4b4) Tb4b4b4{
Te6edf3bt_startTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72trueTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3bt_stopTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3bt_conf_saveTb4b4b4(Tff7b72falseTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72endif T8b949e// BOUNDARY_MODE
Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72volatile Tff7b72bool Te6edf3serial_polling Tff7b72= Tff7b72falseTb4b4b4;
Tff7b72void Te6edf3serial_pollTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3serial_polling Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo_isempty_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72while Tb4b4b4(Tff7b72!Te6edf3fifo_isemptyTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tff7b72char Te6edf3sbyte Tff7b72= Te6edf3fifo_popTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4;
Te6edf3serial_callbackTb4b4b4(Te6edf3sbyteTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3serial_polling Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32
Tff7b72#Tff7b72define MAX_CYCLES 20
Tff7b72#Tff7b72else
Tff7b72#Tff7b72define MAX_CYCLES 10
Tff7b72#Tff7b72endif
Tff7b72void Te6edf3buffer_serialTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3serial_bufferingTb4b4b4) Tb4b4b4{
Te6edf3serial_buffering Tff7b72= Tff7b72trueTb4b4b4;
Tff7b72uint8_t Te6edf3c Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72while Tb4b4b4(
Te6edf3c Tff7b72< Te6edf3MAX_CYCLES Tff7b72&Tff7b72&
Tff7b72#Tff7b72if HAS_WIFI
Tb4b4b4( Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Td2a8ffSerialTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Te6edf3SerialBTTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3wr_state Tff7b72>Tff7b72= Te6edf3WR_STATE_ON Tff7b72&Tff7b72& Te6edf3wifi_remote_availableTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4)
Tff7b72#Tff7b72else
Tb4b4b4( Tb4b4b4(Te6edf3bt_state Tff7b72!Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Td2a8ffSerialTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTED Tff7b72&Tff7b72& Te6edf3SerialBTTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4)
Tff7b72#Tff7b72endif
Tb4b4b4)
Tff7b72#Tff7b72else
Tff7b72while Tb4b4b4(Te6edf3c Tff7b72< Te6edf3MAX_CYCLES Tff7b72&Tff7b72& Td2a8ffSerialTb4b4b4.Td2a8ffavailableTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72#Tff7b72endif
Tb4b4b4{
Te6edf3cTff7b72+Tff7b72+Tb4b4b4;
Tff7b72#Tff7b72if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfull_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_push_lockedTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Td2a8ffSerialTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72elif HAS_BLUETOOTH || HAS_BLE == true || HAS_WIFI
Tff7b72#Tff7b72if HAS_BLUETOOTH || HAS_BLE == true
Tff7b72if Tb4b4b4(Te6edf3bt_state Tff7b72=Tff7b72= Te6edf3BT_STATE_CONNECTEDTb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3SerialBTTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72if HAS_WIFI
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3wifi_host_is_connectedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3wifi_remote_readTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72else Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Td2a8ffSerialTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72elif HAS_WIFI
Tff7b72if Tb4b4b4(Te6edf3wifi_host_is_connectedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Te6edf3wifi_remote_readTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72else Tb4b4b4{ Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Td2a8ffSerialTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4} Tb4b4b4}
Tff7b72#Tff7b72endif
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fifo_isfullTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3fifo_pushTb4b4b4(Tff7b72&Te6edf3serialFIFOTb4b4b4, Td2a8ffSerialTb4b4b4.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Tb4b4b4}
Te6edf3serial_buffering Tff7b72= Tff7b72falseTb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72void Te6edf3serial_interrupt_initTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if MCU_VARIANT == MCU_1284P
Te6edf3TCCR3A Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3TCCR3B Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3CS10Tb4b4b4) Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM33Tb4b4b4)Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM32Tb4b4b4)Tb4b4b4;
T8b949e// Buffer incoming frames every 1ms
Te6edf3ICR3 Tff7b72= T79c0ff16000Tb4b4b4;
Te6edf3TIMSK3 Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3ICIE3Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_2560
T8b949e// TODO: This should probably be updated for
T8b949e// atmega2560 support. Might be source of
T8b949e// reported issues from snh.
Te6edf3TCCR3A Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3TCCR3B Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3CS10Tb4b4b4) Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM33Tb4b4b4)Tff7b72|
Te6edf3_BVTb4b4b4(Te6edf3WGM32Tb4b4b4)Tb4b4b4;
T8b949e// Buffer incoming frames every 1ms
Te6edf3ICR3 Tff7b72= T79c0ff16000Tb4b4b4;
Te6edf3TIMSK3 Tff7b72= Te6edf3_BVTb4b4b4(Te6edf3ICIE3Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif MCU_VARIANT == MCU_ESP32
T8b949e// No interrupt-based polling on ESP32
Tff7b72#Tff7b72endif
Tb4b4b4}
Tff7b72#Tff7b72if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560
Te6edf3ISRTb4b4b4(Te6edf3TIMER3_CAPT_vectTb4b4b4) Tb4b4b4{ Te6edf3buffer_serialTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tff7b72#Tff7b72endif
Served by rngit 1.4.2 - Generated in 0.26s